2009-10-06 4 views
74

Есть ли способ взять список и преобразовать его в строку, разделенную запятой?Преобразование списка <int> в строку, разделенную запятой

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

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

ответ

140
List<int> list = ...; 
string.Join(",", list.Select(n => n.ToString()).ToArray()) 
+5

Умный, но медленный и раздутый, поскольку он выделяет одну строку на элемент. Использование StringBuilder было бы намного более эффективным. –

+3

Из того, что я видел в Интернете (быстрый поиск) String.Join быстрее, чем с помощью StringBuilder. –

+3

http://stackoverflow.com/questions/585860/string-join-vs-stringbuilder-which-is-faster, вы ошибаетесь Steven –

8
List<int> list = new List<int> { 1, 2, 3 }; 
Console.WriteLine(String.Join(",", list.Select(i => i.ToString()).ToArray())); 
+0

Отлично, если вы не можете использовать .NET 4 –

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)); 

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

+1

Пожалуйста, не пишите 'Select' с побочными эффектами в лямбда. В этом случае вы даже не используете 'y', поэтому ваш' Select' по существу является просто 'foreach', поэтому напишите его как таковой. –

+0

Я не предлагал это как хорошее решение. OP хотел чего-то более интересного, чем foreach. – Larsenal

+0

Да, но злоупотребление 'Select' как' foreach' прошло мимо «интересного» и в «правильном». Более интересным подходом здесь было бы использовать «Enumerable.Aggregate» с «StringBuilder» в качестве начального значения - попробуйте это. –

3

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

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

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

List<int> list = new List<int> { 1, 2, 3 }; 
Console.WriteLine(list.BuildString(", ")); 
+0

Две возможные оптимизации: 1) Добавьте разделитель после каждого элемента независимо, затем удалите дополнительный один после окончания цикла. 2) Укажите емкость для StringBuilder. –

+1

Если вы выкапываете Reflector, то получается, что Join суммирует длины, чтобы предварительно вычислить размер буфера, а также «primes the pump», добавив первую строку за пределы цикла, а затем внутри цикла безоговорочно добавив разделитель до следующую строку. В сочетании с некоторыми небезопасными/внутренними трюками это должно быть очень быстро. –

+0

@Steven: последовали за советом. – cdiggins

6

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

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

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

Eric Lippert's challenge "comma-quibbling", best answer?

+0

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

1

Кажется reasonablly быстро.

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)); 
68

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

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

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

+0

Спасибо! это прекрасный подход –

Смежные вопросы