2012-10-13 15 views
13

Ho bisogno di un modo più efficiente di produrre più file dal mio gruppo di dati. Im usando un tipo List<MyObject> e il mio oggetto ha alcune proprietà pubbliche in cui ho bisogno di raggruppare i dati per.C# Groupby Linq e foreach

Ho sentito parlare di Linq e suona come qualcosa che potrei usare. Tuttavia non sono sicuro di come farlo.

Ho bisogno di produrre un file di testo per ogni STATO, quindi raggruppando tutti gli MyObjects (persone) per stato, quindi eseguendo uno foreach sguardo su di essi per creare il file TEXT.

void Main() 
{ 

    List<MyObject> lst = new List<MyObject>(); 
    lst.Add(new MyObject{ name = "bill", state = "nsw", url = "microsoft.com"}); 
    lst.Add(new MyObject{ name = "ted", state = "vic", url = "apple.com"}); 
    lst.Add(new MyObject{ name = "jesse", state = "nsw", url = "google.com"}); 
    lst.Add(new MyObject{ name = "james", state = "qld", url = "toshiba.com"}); 

    string builder = ""; 
    foreach (MyObject item in myObjects) { 

     builder += item.name + "\r\n"; 
     builder += item.url + "\r\n" + "\r\n\r\n"; 

    } 

and out to the `StreamWriter` will be the filenames by state. 

In totale per i dati di cui sopra ho bisogno di 3 file;

-nsw.txt 
-vic.txt 
-qld.txt 

risposta

25

Qualcosa di simile, forse?

var groups = lst.GroupBy(x => x.state); 

    foreach (var group in groups) 
    { 
     using (var f = new StreamWriter(group.Key + ".txt")) 
     { 
      foreach (var item in group) 
      { 
       f.WriteLine(item.name); 
       f.WriteLine(item.url); 
      } 
     } 
    } 
+0

Ha bisogno di una linea vuota supplementare. –

+0

Mi piace perché è più ciò che Im attualmente è abituato. Bello e facile da leggere. – IEnumerable

+0

Anche questo sta usando Linq? – IEnumerable

6

Tu def. potrebbe usare LINQ qui.

lst.GroupBy(r=> r.state).ToList().ForEach(r=> { 
     //state= r.Key 
     // 

     foreach (var v in r) 
     { 

     } 
    }); 

La cosa su linq. Se vuoi sapere come fare qualcosa in esso. Pensa "come lo farei in SQL". Le parole chiave sono per lo più le stesse.

+0

ho notato le somiglianze :) il campione si presenta molto elegante, cercherò di esso. grazie – IEnumerable

0

Qualcosa di simile ...

string builderNsw = ""; 
foreach (MyObject item in lst.Where(o=>o.state == 'nsw')) { 

    builderNsw += item.name + "\r\n"; 
    builderNsw += item.url + "\r\n" + "\r\n\r\n"; 

} 

... ma probabilmente ci sono molti modi per raggiungere questo obiettivo.

+0

sì, ma presumo che questo produrrà solo dati "nsw", ho bisogno di una soluzione pulita che produce tutti gli stati – IEnumerable

1

Si può effettivamente produrre intero contenuto con LINQ:

var entryFormat = "{1}{0}{2}{0}{0}{0}"; 
var groupsToPrint = lst 
    .GroupBy(p => p.state) 
    .Select(g => new 
    { 
     State = g.Key, 
     // produce file content on-the-fly from group entries 
     Content = string.Join("", g.Select(v => string.Format(entryFormat, 
      Environment.NewLine, v.name, v.url))) 
    }); 

var fileNameFormat = "{0}.txt"; 
foreach (var entry in groupsToPrint) 
{ 
    var fileName = string.Format(fileNameFormat, entry.State); 
    File.WriteAllText(fileName, entry.Content); 
} 
0

Idem come sopra - Iterazione attraverso i gruppi dal gruppo, in grado di ottenere il nome del gruppo anche

int itemCounter = 1; 
    IEnumerable<DataRow> sequence = Datatables.AsEnumerable(); 

    var GroupedData = from d in sequence group d by d["panelName"];  // GroupedData is now of type IEnumerable<IGrouping<int, Document>> 

    foreach (var GroupList in GroupedData) // GroupList = "document group", of type IGrouping<int, Document> 
    {   
     bool chk = false; 
     foreach (var Item in GroupList) 
     { 

     if (chk == false) // means when header is not inserted 
     { 
      var groupName = "Panel Name : " + Item["panelName"].ToString(); 

      chk = true; 
     } 
     var count = itemCounter.ToString(); 
     var itemRef = Item["reference"].ToString(); 

     itemCounter++; 
     } 
    }