Преобразование List <int> в строку, разделенную запятыми

116

Есть ли способ взять список и преобразовать его в строку, разделенную запятыми?

Я знаю, что могу просто зациклить и построить его, но почему-то я думаю, что некоторые из вас, ребята, могут это сделать более круто?

Я действительно хочу изучить эти типы «уловок», поэтому, пожалуйста, объясните или дайте ссылку на документацию по методу, который вы используете.

mrblah
источник

Ответы:

189
List<int> list = ...;
string.Join(",", list.Select(n => n.ToString()).ToArray())
Павел Минаев
источник
7
Умный, но медленный и раздутый, так как выделяет одну строку на элемент. Использование StringBuilder было бы намного эффективнее.
Стивен Судит, 06
3
Из того, что я видел в Интернете (быстрый поиск), String.Join работает быстрее, чем использование StringBuilder.
Юрий Факторович
3
stackoverflow.com/questions/585860/… , вы не правы, Стивен
Юрий Факторович
6
Я думаю, что Стивен имеет в виду часть n.ToString (), а не String.Join.
Larsenal 06
9
Larsenal: но StringBuilder.Append (Int32) в любом случае внутренне вызывает ToString для целого числа. StringBuilder не позволяет волшебным образом избежать затрат на выделение строки для каждого элемента; он просто красиво убирает его из поля зрения.
itowlson 07
115

Простое решение

List<int> list = new List<int>() {1,2,3};
string.Join<int>(",", list)

Я использовал это только сейчас в своем коде, работая очень быстро.

Нитин Давэр
источник
1
Спасибо! это прекрасный подход
Ирфан Ашраф
2
Это лучший подход, чем принятый ответ. При таком подходе вам не нужно импортировать Linq, и это быстрее.
JoKeRxbLaCk
Прохладно! Я никогда не знал string. Join имеет общие перегрузки. Спасибо.
mrmashal
10
List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(String.Join(",", list.Select(i => i.ToString()).ToArray()));
Юрий Факторович
источник
Отлично, если вы не можете использовать .NET 4
Грег Вудс
6

Примерно миллиард решений чуть более сложной версии этой проблемы, многие из которых медленные, содержат ошибки или даже не компилируются, см. В комментариях к моей статье на эту тему:

http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-quibbling.aspx

и комментарий StackOverflow:

Вызов Эрика Липперта - «придираться к запятым», лучший ответ?

Эрик Липперт
источник
Спасибо за ссылку. Эта проблема конкатенации строк оказалась более сложной и познавательной, чем я ожидал!
Стивен Судит,
4

Для большей крутизны я бы сделал это методом расширения для IEnumerable <T>, чтобы он работал на любом IEnumerable:

public static class IEnumerableExtensions {
  public static string BuildString<T>(this IEnumerable<T> self, string delim = ",") {
    return string.Join(delim, self)        
  }
}

Используйте его следующим образом:

List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(list.BuildString(", "));
cdiggins
источник
Две возможные оптимизации: 1) Независимо от каждого элемента добавьте разделитель, а затем удалите лишний после завершения цикла. 2) Укажите емкость для StringBuilder.
Стивен Судит, 07
1
Если вы откопаете Reflector, то окажется, что Join суммирует длины для предварительного расчета размера буфера, а также «запускает насос», добавляя первую строку вне цикла, а затем внутри цикла безоговорочно добавляя разделитель перед следующая строка. В сочетании с некоторыми небезопасными / внутренними уловками это должно быть очень быстро.
Стивен Судит, 07
@ Стивен: последовал твоему совету.
cdiggins
1
Вы жестко кодируете разделитель в своем расширении и игнорируете переданное значение в качестве разделителя и пропускаете точку с запятой. Должно бытьreturn string.Join(delim, self);
Эндрю
1

Кажется достаточно быстрым.

IList<int> listItem = Enumerable.Range(0, 100000).ToList();
var result = listItem.Aggregate<int, StringBuilder, string>(new StringBuilder(), (strBuild, intVal) => { strBuild.Append(intVal); strBuild.Append(","); return strBuild; }, (strBuild) => strBuild.ToString(0, strBuild.Length - 1));
Грегори
источник
1

Моя «умная» запись:

        List<int> list = new List<int> { 1, 2, 3 };
        StringBuilder sb = new StringBuilder();
        var y = list.Skip(1).Aggregate(sb.Append(x.ToString()),
                    (sb1, x) =>  sb1.AppendFormat(",{0}",x));

        // A lot of mess to remove initial comma
        Console.WriteLine(y.ToString().Substring(1,y.Length - 1));

Просто не придумал, как условно добавить запятую.

Larsenal
источник
1
Пожалуйста, не пишите Selectс побочными эффектами в лямбде. В этом случае вы даже не используете y, так что ваш, Selectпо сути, просто foreach- так что напишите его как таковой.
Павел Минаев
Я не предлагал это как хорошее решение. OP хотел чего-то более интересного, чем foreach.
Ларсенал 07
Да, но злоупотребление , Selectкак foreachпроходит мимо «интересным» и в, ну, «злоупотребление». Более интересным подходом здесь было бы использование Enumerable.Aggregateс StringBuilderв качестве начального значения - попробуйте.
Павел Минаев
Отличная идея. Мне нужно выйти, но я могу дать этому поворот.
Ларсенал 07
0

вы можете использовать библиотеку System.Linq; Это более эффективно:

using System.Linq;
string str =string.Join(",", MyList.Select(x => x.NombreAtributo));
Маурико Белло
источник