Agrupando Listas em Memória em C# com LINQ e Expressões Lambda

Ao trabalhar com listas em C#, você pode se deparar com vários cenários onde precisa agrupar itens com base em uma propriedade específica. Por exemplo, digamos que você tenha uma coleção de objetos Foo e queira organizá-los com base nos valores das suas propriedades Bar. É aqui que entra o poder do LINQ (Consulta Integrada à Linguagem) e expressões lambda. Neste post, vamos explorar como agrupar listas em memória usando eficazmente esses recursos do C#.

Entendendo o Problema

Imagine que você tem uma lista de objetos Foo, onde cada Foo possui as propriedades Bar e Lum. Algumas instâncias de Foo podem compartilhar o mesmo valor para Bar. Seu objetivo é agrupar essas instâncias de Foo pelos seus valores de Bar e, em seguida, iterar sobre as coleções agrupadas para acessar seus respectivos valores de Lum. Isso pode melhorar a organização dos dados e facilitar a manipulação de conjuntos específicos de dados.

Cenário de Exemplo

Vamos considerar um exemplo específico com a seguinte lista de instâncias Foo:

var foos = new List<Foo> {
   new Foo{Bar = 1,Lum = 1},
   new Foo{Bar = 1,Lum = 2},
   new Foo{Bar = 2,Lum = 3},
};

Resultado Desejado

Queremos agrupar essas instâncias de Foo pelos seus valores de Bar, resultando em algo como:

  • Para Bar = 1: Lum = 1, Lum = 2
  • Para Bar = 2: Lum = 3

Solução Usando LINQ

Você pode agrupar os objetos Foo usando a cláusula group by do LINQ. Veja como isso pode ser alcançado:

var groupedFoos = from foo in foos
                  group foo by foo.Bar into grouped
                  let lums = from g in grouped
                             select g.Lum
                  select new { Bar = grouped.Key, Lums = lums };

Passos Explicados

  • Group By: A parte group foo by foo.Bar agrupa as instâncias de Foo com base na propriedade Bar.
  • Into Grouped: Isso cria um novo escopo para cada grupo.
  • Selecionando Valores de Lum: A instrução let lums permite que você crie uma nova coleção consistindo de valores de Lum dos objetos agrupados.
  • Seleção Final: A seleção final monta tudo em um novo objeto contendo o valor de Bar e sua correspondente lista de valores de Lum.

Solução Usando Expressões Lambda

Alternativamente, você pode alcançar o mesmo resultado usando expressões lambda, que podem oferecer uma sintaxe mais concisa. Veja como:

var groupedFoos = foos.GroupBy(x => x.Bar)
                      .Select(y => new { Bar = y.Key, Lums = y.Select(z => z.Lum) });

Como Funciona

  • GroupBy: Este método aceita uma função lambda para especificar a propriedade pela qual queremos agrupar, a saber, x.Bar.
  • Select: Após o agrupamento, usamos Select para criar um novo objeto anônimo para cada grupo, contendo os valores de Bar e os respectivos valores de Lum.

Iterando Através dos Dados Agrupados

Independentemente de você usar LINQ ou expressões lambda, iterar pelos dados agrupados permanece o mesmo. Você pode percorrer cada grupo e imprimir os valores de Lum da seguinte forma:

foreach (var group in groupedFoos)
{
    Console.WriteLine("Lums for Bar#" + group.Bar);
    foreach (var lum in group.Lums)
    {
        Console.WriteLine(lum);
    }
}

A Saída Será:

Lums for Bar#1
1
2
Lums for Bar#2
3

Conclusão

Agrupar listas em memória usando LINQ ou expressões lambda em C# é uma maneira poderosa de organizar seus dados. Seja você preferindo a legibilidade da sintaxe do LINQ ou a concisão das expressões lambda, ambas as abordagens permitirão que você alcance o agrupamento desejado de seus dados de maneira eficaz.

Para aqueles que desejam aprofundar seu entendimento sobre LINQ, considere explorar 101 Exemplos de LINQ para exemplos mais abrangentes.

Se você tiver alguma dúvida ou quiser compartilhar suas experiências com o agrupamento de dados em C#, sinta-se à vontade para deixar um comentário abaixo!