Cómo obtener valores de IGrouping

211

Tengo una pregunta sobre IGroupingy el Select()método.

Digamos que tengo un IEnumerable<IGrouping<int, smth>>de esta manera:

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

donde listesta a List<smth>.

Y ahora necesito pasar los valores de cada uno IGroupinga otra lista de alguna manera:

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

¿Alguien puede sugerir cómo obtener los valores ( List<smth>) de un IGrouping<int, smth>en ese contexto?

Illia Ratkevych
fuente
El ID generalmente es un campo de identidad que debería ser único, lo que haría que agruparlo fuera inútil, si solo está tratando de eliminar datos duplicados, intente Distinct () en su lugar. si fuera list.GroupBy (x => x.SubID), entonces tendría sentido usar la agrupación, pero en ese caso lo más probable es que desee mantener la agrupación y foreach (var grp en grupos) {grp.ToList () ; } haría eso
MikeT

Respuestas:

277

Desde IGrouping<TKey, TElement>implementos IEnumerable<TElement>, puede usar SelectManypara poner todo de IEnumerablesnuevo en uno IEnumerabletodo junto:

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();
Matt Smith
fuente
3
¿No es lo mismo que un "orderBy" normal? List <smth> newList = list .OrderBy (x => x.id) .ToList ();
MorgoZ
@MorgoZ, la pregunta es acerca de tomar el groupsy volver a una lista plana.
Matt Smith
3
@MorgoZ, OrderBy(x => x.id)los ordenará en orden ascendente por ID. Compare esto con .GroupBy(x => x.id).SelectMany(group => group), que los ordenará por orden de primera aparición de ID. Si las ID originales están en el orden: [1,3,2,2,2,3,0], al agruparlas y luego aplanarlas en una lista colocará las ID en el nuevo orden: [1,3,3, 2,2,2,0].
Pi Fisher
2
No funciona para mí ... dice que el uso no puede inferir el tipo
Anterior
3
tipo no puede inferirse por el uso
Leo Gurdian
34
foreach (var v in structure) 
{     
    var group = groups.Single(g => g.Key == v. ??? );
    v.ListOfSmth = group.ToList();
}

Primero debe seleccionar el grupo deseado. Entonces puede usar el ToListmétodo de en el grupo. El IGroupinges uno IEnumerablede los valores.

Tim se enfría
fuente
17

Versión más aclarada de las respuestas anteriores:

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;
    }
}
Bronek
fuente
No lo creo, al menos por ahora.
snr
15

De la definición de IGrouping:

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

puedes iterar a través de elementos como este:

IEnumerable<IGrouping<int, smth>> groups = list.GroupBy(x => x.ID)
foreach(IEnumerable<smth> element in groups)
{
//do something
}
usuario1275513
fuente
1
que itera a través de él no agrupa los elementos del grupo
MikeT
1
Oh, mi error, entonces: 'foreach (smth p en grupos.SelectMany (sth => sth))'
usuario1275513