Предположим, что у меня есть строка вроде этого:
one two three "four five six" seven eight
и я хочу преобразовать его в это:
one,two,three,"four five six",seven,eight
Какой самый простой способ сделать это на С#?
Здесь появилась более многоразовая функция, с которой я столкнулся:
private string ReplaceWithExceptions(string source, char charToReplace,
char replacementChar, char exceptionChar)
{
bool ignoreReplacementChar = false;
char[] sourceArray = source.ToCharArray();
for (int i = 0; i < sourceArray.Length; i++)
{
if (sourceArray[i] == exceptionChar)
{
ignoreReplacementChar = !ignoreReplacementChar;
}
else
{
if (!ignoreReplacementChar)
{
if (sourceArray[i] == charToReplace)
{
sourceArray[i] = replacementChar;
}
}
}
}
return new string(sourceArray);
}
Использование:
string test = "one two three \"four five six\" seven eight";
System.Diagnostics.Debug.WriteLine(ReplaceWithExceptions(test, char.Parse(" "),
char.Parse(","), char.Parse("\"")));
Предполагая, что кавычки неизбежны, вы можете сделать следующее.
public string SpaceToComma(string input) {
var builder = new System.Text.StringBuilder();
var inQuotes = false;
foreach ( var cur in input ) {
switch ( cur ) {
case ' ':
builder.Append(inQuotes ? cur : ',');
break;
case '"':
inQuotes = !inQuotes;
builder.Append(cur);
break;
default:
builder.Append(cur);
break;
}
}
return builder.ToString();
}
static string Space2Comma(string s)
{
return string.Concat(s.Split('"').Select
((x, i) => i % 2 == 0 ? x.Replace(' ', ',') : '"' + x + '"').ToArray());
}
В моем комментарии к исходному вопросу, если вам не нужны кавычки в конечном результате, это выполнит свою работу. Если вам сделать нужны кавычки, не стесняйтесь игнорировать это.
private String SpaceToComma(string input)
{
String[] temp = input.Split(new Char[] { '"' }, StringSplitOptions.RemoveEmptyEntries);
for (Int32 i = 0; i < temp.Length; i += 2)
{
temp[i] = temp[i].Trim().Replace(' ', ',');
}
return String.Join(",", temp);
}
@Mehrdad избил меня, но думаю, я все равно отправлю его:
static string Convert(string input)
{
var slices = input
.Split('"')
.Select((s, i) => i % 2 != 0
? @"""" + s + @""""
: s.Trim().Replace(' ', ','));
return string.Join(",", slices.ToArray());
}
LINQified и проверено:-)... Для полного консольного приложения: http://pastebin.com/f23bac59b
Для этой цели я бы использовал класс Regex.
Регулярные выражения могут использоваться для соответствия вашим входным данным, разбивать их на отдельные группы, которые затем можно собрать, но вы хотите. Здесь вы можете найти документацию по regex classes.
Regex rx = new Regex( "(\w)|([\"]\w+[\"])" );
MatchCollection matches = rx.Matches("first second \"third fourth fifth\" sixth");
string.Join( ", ", matches.Select( x => x.Value ).ToArray() );
Это может быть излишним, но если вы считаете, что проблема может быть обобщена, например, необходимость разделения на другие типы символов или наличие дополнительных правил, определяющих токен, вы должны рассмотреть либо использование генератора синтаксического анализатора, такого как Coco или написать простой один по своему усмотрению. Например, Coco/R будет генерировать лексер и парсер из грамматики EBNF, которую вы предоставляете. Лексер будет DFA или конечным автоматом, который является обобщенной формой кода, предоставленного JaredPar. Ваше определение грамматики для Coco/R будет выглядеть так:
CHARACTERS
alphanum = 'A'..'Z' + 'a'..'z' + '0'..'9'.
TOKENS
unit = '"' {alphanum|' '} '"' | {alphanum}.
Затем созданный лексер сканирует и упорядочивает ваш вход соответственно.
Мое первое предположение - использовать синтаксический анализатор, который уже написал и просто изменил разделитель и кавычек, соответствующий вашим потребностям (которые есть и "соответственно).
Похоже, это доступно вам в С#: http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx
Возможно, если вы измените разделитель на "", он может удовлетворить ваши потребности в файле, а затем просто вопрос вызова String.Join() a для каждой строки.