Konwersja List <int> na ciąg rozdzielany przecinkami

116

Czy istnieje sposób, aby wziąć Listę i przekonwertować ją na ciąg oddzielony przecinkami?

Wiem, że mogę to po prostu zapętlić i zbudować, ale jakoś myślę, że niektórzy z was to fajniejszy sposób na zrobienie tego?

Naprawdę chcę nauczyć się tego typu „sztuczek”, więc proszę wyjaśnij lub umieść link do dokumentacji na temat używanej metody.

mrblah
źródło

Odpowiedzi:

189
List<int> list = ...;
string.Join(",", list.Select(n => n.ToString()).ToArray())
Pavel Minaev
źródło
7
Sprytny, ale powolny i nadęty, ponieważ przydziela jeden ciąg na element. Korzystanie z StringBuilder byłoby znacznie bardziej wydajne.
Steven Sudit
3
Z tego, co widziałem online (szybkie wyszukiwanie) String.Join jest szybsze niż użycie StringBuilder.
Yuriy Faktorovich
6
Myślę, że Steven odnosi się do części n.ToString (), a nie do String.Join.
Larsenal
9
Larsenal: ale StringBuilder.Append (Int32) i tak wewnętrznie wywołuje ToString na liczbie całkowitej. StringBuilder nie pozwala w magiczny sposób uniknąć kosztów przydzielania ciągu dla każdego elementu; po prostu ładnie go chowa poza zasięgiem wzroku.
itowlson
115

Proste rozwiązanie to

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

Użyłem go właśnie teraz w swoim kodzie, działając przyjemnie.

Nitin Daware
źródło
1
Podziękować! to jest piękne podejście
Irfan Ashraf
2
Jest to lepsze podejście niż akceptowana odpowiedź. Dzięki takiemu podejściu nie musisz importować Linq i jest to szybsze.
JoKeRxbLaCk
Chłodny! Nigdy nie znałem stringów. Join ma ogólne przeciążenia. Dzięki.
mrmashal
10
List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(String.Join(",", list.Select(i => i.ToString()).ToArray()));
Yuriy Faktorovich
źródło
Świetnie, jeśli nie możesz używać platformy .NET 4
Greg Woods
6

W przypadku około jednego miliarda rozwiązań nieco bardziej skomplikowanej wersji tego problemu - z których wiele jest powolnych, zawiera błędy lub nawet się nie kompiluje - zobacz komentarze do mojego artykułu na ten temat:

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

i komentarz StackOverflow:

Wyzwanie Erica Lipperta „sprzeczka przecinkami”, najlepsza odpowiedź?

Eric Lippert
źródło
Dzięki za link. Ten problem z konkatenacją ciągów okazał się bardziej złożony i pouczający, niż się spodziewałem!
Steven Sudit
4

Dla dodatkowego chłodu uczyniłbym to metodą rozszerzającą w IEnumerable <T>, tak aby działała na dowolnym IEnumerable:

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

Użyj go w następujący sposób:

List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(list.BuildString(", "));
cdiggins
źródło
Dwie możliwe optymalizacje: 1) Niezależnie dołącz separator po każdym elemencie, a następnie usuń dodatkowy po zakończeniu pętli. 2) Określ pojemność dla StringBuilder.
Steven Sudit
1
Jeśli wykopiesz Reflector, okaże się, że Join sumuje długości, aby wstępnie obliczyć rozmiar bufora, a także „przygotowuje pompę”, dołączając pierwszy ciąg poza pętlą, a następnie, wewnątrz pętli, bezwarunkowo dodając ogranicznik przed następny ciąg. W połączeniu z pewnymi niebezpiecznymi / wewnętrznymi sztuczkami powinno być bardzo szybkie.
Steven Sudit
@Steven: postąpiłem zgodnie z twoją radą.
cdiggins
1
Zakodowałeś separator na stałe w swoim rozszerzeniu i zignorowałeś przekazaną wartość dla separatora i pominięto średnik. Powinno byćreturn string.Join(delim, self);
Andrew
1

Wydaje się dość szybko.

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));
Gregory
źródło
1

Mój „sprytny” wpis:

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

Po prostu nie wymyśliłem, jak warunkowo dodać przecinek.

Larsenal
źródło
1
Proszę nie pisać Selectz efektami ubocznymi w lambdzie. W tym przypadku nawet nie używasz y, więc Selectzasadniczo jest to po prostu foreach- więc zapisz to jako takie.
Pavel Minaev
Nie sugerowałem tego jako dobrego rozwiązania. OP chciał czegoś ciekawszego niż wszyscy.
Larsenal
Tak, ale nadużywanie, Selectjak foreachto minęło, jest „interesujące” i przechodzi w… Bardziej interesujące podejście tutaj byłoby użyć Enumerable.Aggregateze StringBuilderjako wartość seed - spróbuj tego.
Pavel Minaev
Dobry pomysł. Muszę wyjść, ale mogę nadać temu wir.
Larsenal
0

możesz użyć, biblioteki System.Linq; Jest bardziej wydajna:

using System.Linq;
string str =string.Join(",", MyList.Select(x => x.NombreAtributo));
Maurico Bello
źródło