Перетворення списку <int> у рядок, розділений комами


116

Чи є спосіб взяти список і перетворити його в рядок, розділений комою?

Я знаю, що я можу просто циклічити і побудувати його, але якось я думаю, що хтось із вас, хлопці, більш крутий спосіб це зробити?

Я дуже хочу вивчити ці типи "хитрощів", ​​тому, будь ласка, поясніть або посилайтесь на документи щодо методу, який ви використовуєте.

Відповіді:


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

7
Розумна, але повільна і роздута, оскільки вона виділяє по одній струні на елемент. Використання StringBuilder було б набагато ефективнішим.
— Стівен Судіт

3
З того, що я бачив в Інтернеті (швидкий пошук) String.Join швидше, ніж використання StringBuilder.
— Юрій Факторович


6
Я думаю, що Стівен має на увазі частину n.ToString (), а не String.Join.
— Ларсенал

9
Larsenal: але StringBuilder.Append (Int32) внутрішньо викликає ToString по цілому числу. StringBuilder не магічно уникає витрат на виділення рядка для кожного елемента; це просто красиво витягує його з поля зору.
— itowlson

115

Просте рішення є

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

Я використовував це лише зараз у своєму коді, працюючи у функціоналі.


1
Спасибі! це прекрасний підхід
— Ірфан Ашраф

2
Це кращий підхід, ніж прийнятий відповідь. При такому підході вам не потрібно імпортувати Linq, і це швидше.
— JoKeRxbLaCk

Класно! Я ніколи не знав string.Join має загальні перевантаження. Дякую.
— mrmashal


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(", "));

Дві можливі оптимізації: 1) Додайте деліметр після кожного елемента незалежно, а потім видаліть додатковий після закінчення циклу. 2) Вкажіть ємність для StringBuilder.
— Стівен Судіт

1
Якщо ви викопаєте Reflector, виявиться, що Join підсумовує довжини, щоб попередньо розрахувати розмір буфера, а також "прогрунтує насос", додавши перший рядок поза петлею, а потім, всередині циклу, беззастережно додавши роздільник перед наступний рядок У поєднанні з деякими небезпечними / внутрішніми хитрощами це повинно бути дуже швидким.
— Стівен Судіт

@Steven: дотримуйтесь ваших порад.
— 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));

Просто не зрозумів, як умовно додати кому.


1
Будь ласка, не пишіть Selectз побічними ефектами в лямбда. У цьому випадку ви навіть цього не використовуєте y, тому ваш Selectпо суті є просто foreach- тому запишіть його як таке.
— Павло Мінаєв

Я не пропонував це як гарне рішення. ОП хотіла чогось цікавішого, ніж передбачити
— Larsenal

Так, але зловживання, Selectколи foreachпроходить повз "цікаве" і, ну, "зловживання". Більш цікавий підхід тут повинен був би використовувати Enumerable.Aggregateз StringBuilderяк початкове значення - спробувати.
— Павло Мінаєв

Гарна ідея. Я мушу вийти, але я можу надати цей вир.
— Ларсенал

0

ви можете використовувати бібліотеку System.Linq; Це більш ефективно:

using System.Linq;
string str =string.Join(",", MyList.Select(x => x.NombreAtributo));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.