2011-02-03 7 views
32

У меня есть объект, который содержит много значений, некоторые из них (не все значения из объекта) должны быть помещены в строку csv. Мой подход был таким:Создание разделенных запятыми строк C#?

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

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

+0

Вообще говоря, считается, что менее эффективно конкатенировать строки символом '+'. Это создает больше объектов для сбора мусора. –

+0

[Ручное разделение запятой по сравнению с классным классом CommaDelimitedStringCollection!] (Http://izlooite.blogspot.com/2009/12/manual-comma-separation-versus-cool.html) –

ответ

73

Если вы поместите все свои значения в массив, по крайней мере, вы можете использовать string.Join.

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

Вы также можете использовать перегрузку string.Join, которая принимает params string в качестве второго параметра, как это:

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

+1 для использования массива, между которым сохраняется код более разборчивый, если имеется больше, чем «несколько» значений. – Bazzz

+0

@Bazzz - Да, он может быстро запутаться, если вы введете 10 + параметры в вызов метода соединения. Я думаю, что первый подход - самый чистый, но для нескольких значений, второй - тоже нормально. –

+0

Почему два downvotes на этот ответ? Причина была бы оценена, так что каждый знает, что вы чувствуете, проблема с этим ответом. –

1

Вы можете переопределить метод вашего объекта ToString():

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

Это полезно, только если он точно знает количество элементов, которые он хочет поместить в строку. string.Join, вероятно, лучше подходит. –

+0

Да, но поскольку он хочет создать файл csv, элементы, скорее всего, будут одинаковыми каждый раз. Я не знаю, это вопрос предпочтения. –

+0

Я предполагал из вопроса, что он всегда хочет те же поля, поэтому он определенно знает количество элементов. Ничего плохого в этом ответе, хотя мне не очень нравится переопределять ToString здесь, поскольку это может быть недостаточно общим. +1 от меня все равно. – fearofawhackplanet

3

вы может использовать метод string.Join, чтобы сделать что-то вроде string.Join(",", o.Number, o.Id, o.whatever, ...).

Редактировать: Как digEmAll сказал, string.Join быстрее, чем StringBuilder. Они используют внешнюю реализацию для string.Join.

Профилирование кода (конечно пробег в версии без отладочных символов):

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 взял 2ms на моей машине и StringBuilder.Append 5мс. Поэтому есть заметная разница. Спасибо digAmAll за подсказку.

+2

'string.Join' работает так же быстро, как' StringBuilder' (если не немного быстрее), потому что они оба выделяют только одну строку – digEmAll

+0

Проблема с нормальной строкой concat (например, с помощью string1 + = string2) что исходная строка1 выбрана (поскольку строки неизменяемы), а новая сумма string1 и string2 указана строкой1, и это не очень эффективно, если сделано многократно. Однако, как указывает digEmAll, string.Join, конечно, выделяет строку только один раз. Не один раз для каждого элемента массива. –

+0

Одним из недостатков 'string.Join' (до .NET 4.0) является то, что для него требуется массив строк, заставляя вас выделить его, если у вас есть только общий« IEnumerable »... в любом случае .NET 4.0 исправил эту проблему – digEmAll

1

Если вы используете .NET 4 вы можете использовать перегрузку для string.Join, который принимает IEnumerable, если они у вас есть в списке, тоже:

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

Другой подход заключается в использовании класса CommaDelimitedStringCollection из системы .Configuration namespace/assembly. Он ведет себя как список плюс у него есть переопределенный метод ToString, который возвращает строку, разделенную запятыми.

Плюсы - Более гибкие, чем массив.

Против - вы не можете передать строку, содержащую запятую.

CommaDelimitedStringCollection list = new CommaDelimitedStringCollection(); 

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

string s = list.ToString(); //Huey,Dewey,Louie 
Смежные вопросы