Como obter valores do IGrouping

211

Eu tenho uma pergunta sobre IGroupinge o Select()método.

Digamos que eu tenho um IEnumerable<IGrouping<int, smth>>desta maneira:

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

onde listé uma List<smth>.

E agora eu preciso passar valores de cada um IGroupingpara outra lista de alguma forma:

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

Alguém pode sugerir como obter os valores ( List<smth>) de um IGrouping<int, smth>nesse contexto?

Illia Ratkevych
fonte
O ID geralmente é um campo de identidade que deve ser único, o que tornaria inútil o agrupamento por ele, se você estiver apenas tentando remover dados duplicados, tente Distinct (). se fosse list.GroupBy (x => x.SubID), faria sentido usar o agrupamento, mas nesse caso você provavelmente desejaria manter o agrupamento e a pesquisa (var grp in groups) {grp.ToList () ; } faria isso
MikeT 18/11/2013

Respostas:

277

Desde os IGrouping<TKey, TElement>implementos IEnumerable<TElement>, você pode usar SelectManypara juntar todas as IEnumerablescostas de volta em uma IEnumerable:

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
fonte
3
Não é o mesmo que um "orderBy" normal? List <smth> newList = list .OrderBy (x => x.id) .ToList ();
MorgoZ
@MorgoZ, a questão é pegar groupse voltar para uma lista simples.
Matt Smith
3
@MorgoZ, OrderBy(x => x.id)os classificará em ordem crescente por ID. Compare isso com .GroupBy(x => x.id).SelectMany(group => group), que os classificará pela ordem da primeira aparição do ID. Se os IDs originais estiverem na ordem: [1,3,2,2,2,3,0], agrupá-los e achatar em uma lista colocará os IDs na nova ordem: [1,3,3, 2,2,2,0].
21317 Pi Pi Fisher
2
É does't trabalho para mim .. ele diz que o tipo não pode ser inferida pelo uso
Revious
3
tipo não pode ser inferida pelo uso
Leo Gurdian
34
foreach (var v in structure) 
{     
    var group = groups.Single(g => g.Key == v. ??? );
    v.ListOfSmth = group.ToList();
}

Primeiro você precisa selecionar o grupo desejado. Então você pode usar o ToListmétodo de no grupo. O IGroupingé um IEnumerabledos valores.

Tim Cools
fonte
17

Versão mais esclarecida das respostas acima:

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
fonte
Acho que não, pelo menos por enquanto.
snr 19/04
15

Da definição de IGrouping:

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

você pode simplesmente percorrer elementos como este:

IEnumerable<IGrouping<int, smth>> groups = list.GroupBy(x => x.ID)
foreach(IEnumerable<smth> element in groups)
{
//do something
}
user1275513
fonte
1
que percorre ele grupos não os artigos do grupo
miket
1
Oh meu erro, então: 'foreach (p smth em groups.SelectMany (sth => sth))'
user1275513