LINQ - Usando ToDictionary() e ToList() - II


Hoje vamos continuar a mostrar a utilização dos métodos de extensão ToDictionary() e ToList() da LINQ.

Continuando a primeira parte do artigo vamos tratar com o método ToDictionary().

LINQ : Usando ToDictionary()

Se ToList() pega um IEnumerable<T> e o converte em List<T>, adivinhe o que ToDictionary() faz..?

Basicamente, ToDictionary() é um método muito útil para pegar os resultados de uma consulta (ou qualquer IEnumerable <T>) e organizá-los em um Dictionary<TKey, TValue>.

O truque é definir como o T é convertido em TKey e TValue respectivamente.

Digamos que temos nossa lista de produtos e queremos colocá-la em um Dictionary<int, Produto> para que possamos obter os tempos de pesquisa mais rápidos possíveis com base no ID.

Bem, você poderia fazer algo assim:

var produtos = Produto.GetProdutos();
var resultado = new Dictionary<int, Produto>();
foreach (var produto in produtos)
{
    resultado.Add(produto.Id, produto);
}

Mas este código seria uma redundância pois basta duas linhas de código para obter o mesmo resultado:

var produtos = Produto.GetProdutos();

var resultado1 = produtos.ToDictionary(prod => prod.Id, prod => prod.Nome);

Podemos confirmar o examinando o valor de resultado1:



Este código cria um Dictionary<int, string> onde a chave é a propriedade Id e o valor é a propriedade Nome de cada Produto. Como você pode ver, este método tem muito poder para processar IEnumerable<T> a partir de uma coleção ou de um resultado de consulta em um dicionário.

E se eu precisar de um dicionário que contenha listas de grupos lógicos ?

Então, em nosso exemplo, digamos que queremos criar um Dictionary<string, List<Produto>> de modo que a chave seja uma Categoria e o valor seja a lista de todos os produtos nessa categoria.

Bem,  se você gosta de exercício físico pode teclar este código:

        static void Main(string[] args)
        {
            var produtos = Produto.GetProdutos();
            var resultado = new Dictionary<string, List<Produto>>();
            foreach (var produto in produtos)
            {
                List<Produto> subLista;
                // Se não tem a categoria cria uma nova lista e incluir no dicionario
                if (!resultado.TryGetValue(produto.Categoria, out subLista))
                {
                    subLista = new List<Produto>();
                    resultado.Add(produto.Categoria, subLista);
                }
                //inclui o produto na nova sublista
                subLista.Add(produto);
            }
            Console.ReadLine();
        }

Criamos um monte de código para fazer algo simples. 

Felizmente,  podemos aproveitar as vantagens de ToDictionary () e ToList() para simplificar e com a ajuda do método de extensão LINQ GroupBy() vamos obter o mesmo resultado com o seguinte código:

var produtos = Produto.GetProdutos();
 var resultado = produtos.GroupBy(prod => prod.Categoria)
                       .ToDictionary(group => group.Key, group => group.ToList());

Executando o código e examinando o valor de resultado vamos constatar o seguinte:

No código a cláusula GroupBy() é a consulta de expressão LINQ que cria um IGrouping com um campo Key e também é um IEnumerable dos itens no grupo.

Assim que fizemos GroupBy(), tudo o que tivemos que fazer foi converter esses grupos em um dicionário, então nosso seletor de chave (group => group.Key) pega o campo de agrupamento (Categoria) e o torna a chave no dicionário, e o seletor de valor (group => group.ToList ()) pega os itens do grupo e os converte em uma List<Produto> como o valor do nosso dicionário!

Muito mais fácil de ler e escrever e muito menos código para manter e testar.

Pegue o projeto completo aqui : Linq_ToListToDictionary2.zip

"Mas o fruto do Espírito é: amor, gozo, paz, longanimidade, benignidade, bondade, fé, mansidão, temperança.
Contra estas coisas não há lei."

Gálatas 5:22,23

Referências:


José Carlos Macoratti