2011-02-03 15 views
32

Mam obiekt, który przechowuje wiele wartości, niektóre z nich (nie wszystkie wartości z obiektu) muszą być umieszczone w łańcuchu CSV. Moje podejście było następujące:Utwórz ciągi oddzielone przecinkami C#?

string csvString = o.number + "," + o.id + "," + o.whatever .... 

Jakoś wydaje mi się, że istnieje lepszy, bardziej elegancki sposób?

+0

Zasadniczo uważa się za mniej wydajne łączenie łańcuchów z symbolem '+ '. Tworzy więcej obiektów do zbierania śmieci. –

+0

[Ręczne oddzielanie przecinków a chłodna klasa CommaDelimitedStringCollection!] (Http://izlooite.blogspot.com/2009/12/manual-comma-separation-versus-cool.html) –

Odpowiedz

73

Jeśli umieścisz wszystkie swoje wartości w tablicy, możesz przynajmniej użyć string.Join.

string[] myValues = new string[] { ... }; 
string csvString = string.Join(",", myValues); 

Można również użyć przeciążenie string.Join że trwa params string jako drugi parametr jak poniżej:

string csvString = string.Join(",", value1, value2, value3, ...); 
+0

+1 za używanie tablicy pomiędzy, która utrzymuje kod jest bardziej czytelny, gdy jest więcej niż "kilka" wartości. – Bazzz

+0

@Bazzz - Tak, może szybko stać się brudny, jeśli wprowadzisz 10+ parametrów w wywołaniu metody łączenia. Myślę, że pierwsze podejście jest najczystsze, ale dla kilku wartości drugi jest również w porządku. –

+0

Dlaczego dwa downwotes na tę odpowiedź? Powód byłby doceniany, więc każdy wie, co czujesz, jest problem z tą odpowiedzią. –

1

mogłyby przesłonić metody toString() Twojego obiektu:

public override string ToString() 
{ 
    return string.Format ("{0},{1},{2}", this.number, this.id, this.whatever); 
} 
+0

Jest to przydatne tylko wtedy, gdy dokładnie zna liczbę elementów, które chce umieścić w łańcuchu. string.Join jest prawdopodobnie lepszym rozwiązaniem. –

+0

Tak, ale ponieważ chce utworzyć plik csv, elementy będą najprawdopodobniej za każdym razem takie same. Nie wiem, to kwestia preferencji. –

+0

Przyjąłem z pytania, że ​​zawsze chce tych samych pól, więc na pewno zna liczbę elementów. Nie ma nic złego w tej odpowiedzi, chociaż tak naprawdę nie lubię przesłonić ToString tutaj, ponieważ może nie być wystarczająco ogólny cel. +1 ode mnie w każdym razie. – fearofawhackplanet

3

ty może użyć metody string.Join, aby zrobić coś takiego jak string.Join(",", o.Number, o.Id, o.whatever, ...).

edytuj: Jak powiedział digEmAll, string.Join jest szybszy niż StringBuilder. Używają zewnętrznej implementacji dla ciągu.Join.

Profilowanie kodu (oczywiście prowadzony w wydaniu bez symboli debugowania):

class Program 
{ 
    static void Main(string[] args) 
    { 
     Stopwatch sw = new Stopwatch(); 
     string r; 
     int iter = 10000; 

     string[] values = { "a", "b", "c", "d", "a little bit longer please", "one more time" }; 

     sw.Restart(); 
     for (int i = 0; i < iter; i++) 
      r = Program.StringJoin(",", values); 
     sw.Stop(); 
     Console.WriteLine("string.Join ({0} times): {1}ms", iter, sw.ElapsedMilliseconds); 

     sw.Restart(); 
     for (int i = 0; i < iter; i++) 
      r = Program.StringBuilderAppend(",", values); 
     sw.Stop(); 
     Console.WriteLine("StringBuilder.Append ({0} times): {1}ms", iter, sw.ElapsedMilliseconds); 
     Console.ReadLine(); 
    } 

    static string StringJoin(string seperator, params string[] values) 
    { 
     return string.Join(seperator, values); 
    } 

    static string StringBuilderAppend(string seperator, params string[] values) 
    { 
     StringBuilder builder = new StringBuilder(); 
     builder.Append(values[0]); 
     for (int i = 1; i < values.Length; i++) 
     { 
      builder.Append(seperator); 
      builder.Append(values[i]); 
     } 
     return builder.ToString(); 
    } 
} 

string.join wziął 2ms na moim komputerze i StringBuilder.Append 5ms. Jest więc różnica godna uwagi. Dzięki digAmAll za podpowiedź.

+2

'string.Join' jest tak szybki jak' StringBuilder' (jeśli nie nieco szybszy), ponieważ oba przydzielają tylko jeden ciąg znaków – digEmAll

+0

Problem z normalnym łańcuchem znaków (np. Za pomocą string1 + = string2) jest oryginalny łańcuch 1 jest odrzucany (ponieważ łańcuchy są niezmienne), a nowa suma string1 i string2 jest wskazywana przez string1, co nie jest zbyt wydajne, jeśli jest wykonywane wielokrotnie. Jednak, jak wskazuje digEmAll, string.Join, oczywiście, alokuje łańcuch tylko raz. Nie raz dla każdego elementu w tablicy. –

+0

Jedną z wad 'string.Join' (aż do .NET 4.0) jest to, że wymaga tablicy łańcuchów, zmuszając do przydzielenia jednego, jeśli masz tylko ogólne' IEnumerable '... tak czy inaczej .NET 4.0 rozwiązał ten problem – digEmAll

1

Jeśli używasz .NET Framework 4 można użyć przeciążenie dla string.Join że zajmuje IEnumerable, jeśli masz je na liście, za:

string.Join(", ", strings); 
6

Innym podejściem jest użycie klasy CommaDelimitedStringCollection z systemu .Konfiguracja przestrzeni nazw/złożenia. Zachowuje się jak lista plus ma przesłoniętą metodę ToString, która zwraca ciąg znaków oddzielany przecinkami.

Plusy - bardziej elastyczne niż tablica.

Przeciw - Nie można przekazać ciągu znaków zawierającego przecinek.

CommaDelimitedStringCollection list = new CommaDelimitedStringCollection(); 

list.AddRange(new string[] { "Huey", "Dewey" }); 
list.Add("Louie"); 
//list.Add(","); 

string s = list.ToString(); //Huey,Dewey,Louie 
Powiązane problemy