2010-05-03 7 views
16

Salve Vorrei prendere una raccolta di elenchi e generare una singola riga csv. Quindi prendi questo;Crea CSV dall'elenco di stringhe in LINQ

List<string> MakeStrings() 
{ 
    List<string> results = new List<string>(); 
    results.add("Bob"); 
    results.add("Nancy"); 
    results.add("Joe"); 
    results.add("Jack"); 
    return results;  
} 


string ContactStringsTogether(List<string> parts) 
{ 
    StringBuilder sb = new StringBuilder(); 

    foreach (string part in parts) 
    { 
     if (sb.Length > 0) 
      sb.Append(", "); 

     sb.Append(part); 
    } 
    return sb.ToString(); 
} 

Ciò restituisce "Bob, Nancy, Joe, Jack"

cerca di aiuto sul LINQ per fare questo in una singola istruzione. Grazie!

risposta

24

Non ci sono fodere per farlo con LINQ. Si noti che è possibile utilizzare il metodo Aggregate per eseguire questa operazione, ma si utilizzerà la concatenazione di stringhe anziché un oggetto StringBuilder. Vorrei prendere in considerazione l'aggiunta di un metodo di estensione per questo se qualcosa si farà spesso:

public static string ToCsv<T>(this IEnumerable<T> source) 
    { 
     if (source == null) throw new ArgumentNullException("source"); 
     return string.Join(",", source.Select(s => s.ToString()).ToArray()); 
    } 
+0

Questo è esattamente quello che stavo cercando. Questo non è per la costruzione in un file CSV, è solo per unirsi a mettere su una vista. Eccellente! – CmdrTallen

+0

+1 Voglio solo dire .. bello! –

10
var csv = string.Join(",", MakeStrings().ToArray()); 

vorrei Consiglieresti personalmente utilizzando un vero e proprio CSV parser invece di cercare di fare uno liners che si romperà se i valori contengono una virgola, per esempio. Si può leggere questo articolo su rolling your own CSV parser.

+2

string str = string.Join (",", MakeStrings()); –

+1

@ user129206 dipende dalla versione .net. In 3.5 o precedenti 'string.Join()' aveva solo sovraccarichi di array. –

2

È possibile utilizzare

String csv = parts.Aggregate((s1,s2) => s1+","+s2); 
4

utilizzando LINQ per costruire un CSV in una singola istruzione non può essere una grande idea - soprattutto se la quantità di dati è signficant. Solo perché qualcosa è possibile con LINQ non significa che sia automaticamente il modo migliore per farlo.

Costruire una stringa CSV è, per sua natura, un'operazione che richiede la concatenazione e la riallocazione delle stringhe. È possibile utilizzare String.Join(), ma non eseguirà l'escape automatico di caratteri come virgole o virgolette. In effetti, ci sono un certo numero di regole non banali che fanno parte della generazione di file CSV ben formati.

Quello che dovresti prendere in considerazione è usare un proven library che genera dati CSV corretti.

Se si sceglie di scrivere la propria implementazione, si tenga presente che le tecniche che implicano la concatenazione di più stringhe (come lo Enumerable.Aggregate() offerto come esempio) possono comportare molte istanze di stringa intermedie, che trascinano verso il basso le prestazioni . Probabilmente vorrai comunque utilizzare uno StringBuilder in qualsiasi implementazione del mondo reale.

A volte la struttura più chiara e semplice per il codice è ancora un ciclo.

1

ho praticamente solo utilizzare questa funzione per generare csv da LINQ. Non è perfetto, ma personalizzabile.

public string generateCsvFromLinqQueryable(IQueryable query,string delimiter,string replaceDelimiterInDataWith) 
{ 
    PropertyInfo[] rowPropertyInfos = null; 
    rowPropertyInfos = query.ElementType.GetProperties(); 

    string result = ""; 
    foreach (var myObject in query) 
    { 
     foreach (PropertyInfo info in rowPropertyInfos) 
     { 
      if (info.CanRead) 
      { 
       string tmp = Convert.ToString(info.GetValue(myObject, null)); 
       if (!String.IsNullOrEmpty(tmp)) 
       { 
        tmp.Replace(delimiter, replaceDelimiterInDataWith); 
       } 
       result += tmp + delimiter; 
      } 
     } 
     result += "\r\n"; 
    } 
    return result; 
} 

Harry

1

In .NET 4.0,

string str = string.Join(", ", MakeStrings()); 

aggiungendo il mio risposta qui come un separato, in modo che sarà più chiaro per i lettori, non è chiaro nei miei commenti sotto Darin Dimitrov's risposta.

Problemi correlati