2011-12-15 8 views
132

Ho una domanda sui metodi IGrouping e Select().Come ottenere i valori dall'IGrouping

Diciamo che ho IEnumerable<IGrouping<int, smth>> in questo modo:

var groups = list.GroupBy(x => x.ID); 

cui lista è un List<smth>.

E ora ho bisogno di passare i valori di ogni IGrouping ad un'altra lista in qualche modo .:

foreach (var v in structure) 
{ 
    v.ListOfSmth = groups.Select(...); // <- ??? 
} 

Qualcuno può suggerire come ottenere valori (List<smth>) da IGrouping<int, smth> in tale contesto?

+0

ID è di solito un campo di identità che dovrebbe essere unico, che renderebbe raggruppamento per inutile, se il vostro solo cercando di rimuovere i dati duplicati cercano distinti(), invece. se fosse list.GroupBy (x => x.SubID) allora avrebbe senso usare il raggruppamento, ma in questo caso si preferirebbe mantenere il raggruppamento e il foreach (var grp in gruppi) {grp.ToList() ; } lo farebbe – MikeT

risposta

193

Dal IGrouping<TKey, TElement> implementa IEnumerable<TElement>, è possibile utilizzare SelectMany mettere tutti i IEnumerables di nuovo in uno IEnumerable tutti insieme:

List<smth> list = new List<smth>(); 
IEnumerable<IGrouping<int, smth>> groups = list.GroupBy(x => x.id); 
IEnumerable<smth> smths = groups.SelectMany(group => group); 
List<smth> newList = smths.ToList(); 
+2

Non è lo stesso di un normale "orderBy"? List newList = list .OrderBy (x => x.id) .ToList(); – MorgoZ

+0

@MorgoZ, la domanda è prendere i 'gruppi' e tornare ad una lista semplice. –

+1

@MorgoZ, 'OrderBy (x => x.id)' li ordinerà in ordine crescente per ID. Confrontalo con '.GroupBy (x => x.id) .SelectMany (group => group)', che li ordinerà per ordine di prima apparizione dell'ID. Se gli ID originali sono nell'ordine: [1,3,2,2,2,3,0], quindi raggrupparli e quindi spianarsi in un'unica lista inseriranno gli ID nel nuovo ordine: [1,3, 3,2,2,2,0]. –

24
foreach (var v in structure) 
{  
    var group = groups.Single(g => g.Key == v. ???); 
    v.ListOfSmth = group.ToList(); 
} 

Per prima cosa è necessario selezionare il gruppo desiderato. Quindi è possibile utilizzare il metodo ToList del gruppo. Il IGrouping è un IEnumerable dei valori.

7

Da definizione di IGrouping:

IGrouping<out TKey, out TElement> : IEnumerable<TElement>, IEnumerable 

si può semplicemente scorrere gli elementi In questo modo:

IEnumerable<IGrouping<int, smth>> groups = list.GroupBy(x => x.ID) 
foreach(IEnumerable<smth> element in groups) 
{ 
//do something 
} 
+0

che itera attraverso lui gruppi non gli elementi nel gruppo – MikeT

+0

Oh mio errore, quindi: 'foreach (smth p in groups.SelectMany (sth => sth)) ' – user1275513

8

Versione più chiarito di risposte di cui sopra:

IEnumerable<IGrouping<int, ClassA>> groups = list.GroupBy(x => x.PropertyIntOfClassA); 

foreach (var groupingByClassA in groups) 
{ 
    int propertyIntOfClassA = groupingByClassA.Key; 

    //iterating through values 
    foreach (var classA in groupingByClassA) 
    { 
     int key = classA.PropertyIntOfClassA; 
    } 
}