Генерация значений, разделенных запятыми - PullRequest
9 голосов
/ 07 августа 2009

Предположим, у меня есть коллекция строк:

"foo"
"bar"
"xyz"

И я хотел бы сгенерировать значения из списка через запятую во что-то вроде:

"foo, bar, xyz"

Обратите внимание на отсутствие "," в конце.

Я знаю, что есть десятки способов создать это:

  • использовать for-loop и string.Format () или StringBuilder.
  • использовать счетчик целых чисел и убрать окончание ",", если значение> 0
  • не ставьте "," при первом запуске
  • и т.д.

Пример кода того, что у меня сейчас есть:

if (strs.Count() > 0)
{
  var sb = new StringBuilder();
  foreach (var str in strs)
    sb.AppendFormat("{0}, ", str);
  return sb.Remove(0, 2).ToString();
}

Какой самый лучший код, который можно многократно использовать для вышеуказанного сценария, и почему?

Ответы [ 7 ]

26 голосов
/ 07 августа 2009

Вы хотите использовать метод string.Join, который существует в BCL для этой цели.

Пример:

var myArray = new string[] { "one", "two", "three" };
var output = string.Join(", ", myArray);

Или, если вы используете .NET 3.5, вы можете сделать это с любым IEnumerable<string> следующим образом:

var output = string.Join(", ", myEnumerable.ToArray());

(Обратите внимание, что это не дает наилучшей производительности, как это требуется, хотя, очевидно, оно по-прежнему равно 'O (n)' и должно подходить почти для всех случаев).

Теперь, если ваш перечисляемый тип не имеет типа string (обычно IEnumerable<T>), вы можете просто использовать метод Select для преобразования результата в строку, например,

var output = string.Join(", ", myEnumerable.Select(e => e.ToString()).ToArray());

Я не уверен, что вы имеете дело со значениями, которые потенциально могут содержать запятые в себе, но это можно обойти, заключив их в кавычки (") и экранируя кавычки, аналогично формату CSV.

var output = string.Join(", ", items.Select(x => x.Contains(",") ?
    "\"" + x.Replace("\"", "\"\"") + "\"" : x);

Конечно, разделить их снова - это задача немного сложнее, требующая регулярных выражений.

4 голосов
/ 07 августа 2009

String.Join - правильный ответ, но в случае IEnumerable Linq часто короче цикла for:

someStringCollection.Aggregate((first, second) => first + ", " + second);
4 голосов
/ 07 августа 2009

Как уже говорили другие: String.Join - это обычно лучший способ сделать это. Но что, если у вас просто есть IEnumerable, а не массив? Возможно, у вас есть код для их перечисления, когда вы читаете их из файла, используя отложенное выполнение. В этом случае String.Join не так хорош, потому что вам нужно дважды зациклить строки & mdash; один раз, чтобы создать массив и один раз, чтобы присоединиться к нему. В этом случае вы хотите что-то более похожее на это:

public static string ToDelimitedString(this IEnumerable<string> source, string delimiter)
{
    string d = "";
    var result = new StringBuilder();

    foreach( string s in source)
    {
       result.Append(d).Append(s);
       d = delimiter;
    } 
    return result.ToString();
}

Это будет выполнять почти , а также String.Join, и работает в более общем случае. Затем, учитывая массив строк или любой другой IEnumerable, вы можете назвать его так:

string finalStr = MyStrings.ToDelimitedString(",");
3 голосов
/ 07 августа 2009
string finalstr = String.Join(",", strs);
2 голосов
/ 07 августа 2009

Используйте

string s = string.Join (",", new string[] {"aaa", "bbb", "ccc"});
0 голосов
/ 07 августа 2009

Если у вас есть массив строк, используйте решение Noldorin .

Но если это какой-то другой тип коллекции, я мог бы сделать это:

if (strs.Count() > 0)
{
  var sb = new StringBuilder();
  foreach (var str in strs)
    sb.AppendFormat("{0} {1}", (0 == sb.Length ? "" : ","), str);
  return sb.ToString();
}
0 голосов
/ 07 августа 2009

Использование String.Join

...