Nos últimos tempos, participando do fórum do MSND sobre LINQ (http://social.msdn.microsoft.com/Forums/pt-br/linqpt/threads ), notei que muitas dúvidas surgiram com relação a sintaxe do LINQ para o agrupamento de dados. Dessa forma, espero neste post fazer um breve overview da sintaxe do LINQ para agrupamento, e também demonstrar a sintaxe Lambda correspondente.
Contexto do exemplo
Para estes exemplos utilizei uma estrutura de dados chamada Cidade. Esta estrutura contém: o nome da cidade, a quantidade de habitantes que ali vivem e o estado desta cidade dentro do país.
Os dados utilizados para a execução do exemplo estão chumbados no código e são originados do seguinte método:
private IEnumerable<Cidade> GetCidades() { yield return new Cidade() { Estado = "SP", Habitantes = 11316149, Nome = "São Paulo" }; yield return new Cidade() { Estado = "SP", Habitantes = 1088611, Nome = "Campinas" }; yield return new Cidade() { Estado = "SP", Habitantes = 1222357, Nome = "Guarulhos" }; yield return new Cidade() { Estado = "RJ", Habitantes = 6323037, Nome = "Rio de Janeiro" }; yield return new Cidade() { Estado = "RJ", Habitantes = 37575, Nome = "Parati" }; yield return new Cidade() { Estado = "AM", Habitantes = 1832423, Nome = "Manaus" }; yield return new Cidade() { Estado = "MG", Habitantes = 7002, Nome = "Belo Horizonte" }; yield return new Cidade() { Estado = "MG", Habitantes = 2375444, Nome = "Tiradentes" }; yield return new Cidade() { Estado = "BA", Habitantes = 2676606, Nome = "Salvador" }; }
Agora que temos nossos dados fakes, podemos começar a trabalhar com o LINQ.
Agrupamento simples
Este agrupamento retorna todos os valores contidos na propriedade Estado sem a repetição dos itens, devido o agrupamento ser feito pela própria propriedade Estado.
IEnumerable<Cidade> cidades = GetCidades(); // Lambda var group1 = cidades.GroupBy(c => c.Estado) .Select(group => new { NomeEstado = group.Key }); // LINQ var group2 = from c in cidades group c by c.Estado into myGroupTemp select new { NomeEstado = myGroupTemp.Key };
Este mesmo comportamento pode ser reproduzido com o comando Distinct, que tem o objetivo de apenas trazer elementos distintos (sem repetição) de uma sequência de elementos.
IEnumerable<Cidade> cidades = GetCidades(); // Lambda var distinct1 = cidades.Select(c => c.Estado).Distinct();
Somatória
Este agrupamento, ao contrário do anterior, retorna mais de um campo. Este agrupamento executa o agrupamento com base em um campo e execução uma função no segundo campo. Esta função pode ser uma média, uma soma, um cálculo de valor mínimo ou um cálculo de valor máximo.
IEnumerable<Cidade> cidades = GetCidades(); // Lambda var sum1 = cidades.GroupBy(c => c.Estado) .Select(group => new { NomeEstado = group.Key, HabitantesPorEstado = group.Sum(s => s.Habitantes) }); // LINQ var sum2 = from c in cidades group c by c.Estado into myGroupTemp select new { NomeEstado = myGroupTemp.Key, HabitantesPorEstado = myGroupTemp.Sum(s => s.Habitantes) };
Por
Fernando Henrique Inocêncio Borba Ferreira