É um cruzamento entre um IGrouping
e um dicionário. Permite agrupar itens por uma chave, mas depois acessá-los através dessa chave de maneira eficiente (em vez de apenas iterar sobre todos eles, é isso que GroupBy
permite fazer).
Por exemplo, você pode pegar uma carga de tipos .NET e criar uma pesquisa por namespace ... e acessar todos os tipos em um namespace específico com muita facilidade:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
public class Test
{
static void Main()
{
// Just types covering some different assemblies
Type[] sampleTypes = new[] { typeof(List<>), typeof(string),
typeof(Enumerable), typeof(XmlReader) };
// All the types in those assemblies
IEnumerable<Type> allTypes = sampleTypes.Select(t => t.Assembly)
.SelectMany(a => a.GetTypes());
// Grouped by namespace, but indexable
ILookup<string, Type> lookup = allTypes.ToLookup(t => t.Namespace);
foreach (Type type in lookup["System"])
{
Console.WriteLine("{0}: {1}",
type.FullName, type.Assembly.GetName().Name);
}
}
}
Normalmente, eu usaria var
a maioria dessas declarações no código normal.
Lookup<,>
é simplesmente uma coleção imutável (semAdd
método para, por exemplo), que tem um uso limitado. Além disso, não é uma coleção de propósito geral, no sentido de que, se você pesquisar uma chave inexistente, obterá uma sequência vazia em vez de uma exceção, que é significativa apenas em contextos especiais, por exemplo, com linq. Isso vai bem com o fato de que a MS não forneceu um construtor público para a classe.Uma maneira de pensar sobre isso é:
Lookup<TKey, TElement>
é semelhante aDictionary<TKey, Collection<TElement>>
. Basicamente, uma lista de zero ou mais elementos pode ser retornada através da mesma chave.fonte
Um uso de
Lookup
poderia ser reverter aDictionary
.Suponha que você tenha uma lista telefônica implementada como um
Dictionary
com vários nomes (exclusivos) como chaves, cada nome associado a um número de telefone. Mas duas pessoas com nomes diferentes podem compartilhar o mesmo número de telefone. Isso não é um problema para aDictionary
, que não se importa que duas chaves correspondam ao mesmo valor.Agora você deseja descobrir a quem pertence um determinado número de telefone. Você constrói um
Lookup
, adicionando tudoKeyValuePairs
do seuDictionary
, mas para trás, com o valor como chave e a chave como valor. Agora você pode consultar um número de telefone e obter uma lista de nomes de todas as pessoas cujo número de telefone é esse. Criar umDictionary
com os mesmos dados eliminaria os dados (ou falharia, dependendo de como você o fez), já que fazer issosignifica que a segunda entrada substitui a primeira - o Doc não está mais listado.
Tentando escrever os mesmos dados de uma maneira ligeiramente diferente:
lançaria uma exceção na segunda linha, pois você não pode
Add
uma chave que já esteja naDictionary
.[Obviamente, você pode querer usar alguma outra estrutura de dados única para fazer pesquisas nas duas direções, etc. Este exemplo significa que você precisa regenerar
Lookup
aDictionary
cada vez que ela mudar. Mas para alguns dados, pode ser a solução certa.]fonte
Eu não o usei com sucesso antes, mas aqui está a minha chance:
A
Lookup<TKey, TElement>
se comportaria como um índice de banco de dados (relacional) em uma tabela sem uma restrição exclusiva. Use-o nos mesmos lugares que você usaria o outro.fonte
Acho que você poderia argumentar dessa maneira: imagine que você está criando uma estrutura de dados para armazenar o conteúdo de uma lista telefônica. Você deseja digitar por sobrenome e depois por nome. Usar um dicionário aqui seria perigoso, porque muitas pessoas podem ter o mesmo nome. Portanto, um dicionário sempre será, no máximo, mapeado para um único valor.
Uma pesquisa mapeará para vários valores potencialmente.
A pesquisa ["Smith"] ["John"] será uma coleção do tamanho de um bilhão.
fonte
Lookup["Smith"]["John"]
?