ILookup <TKey, TVal> vs. IGrouping <TKey, TVal>

votos
64

Eu tenho tido problemas para articular as diferenças entre ILookup<TKey, TVal>e IGrouping<TKey, TVal>, e estou curioso se eu entendi corretamente agora. LINQ agravado o problema através da produção de seqüências de IGroupingitens ao mesmo tempo, dando-me um ToLookupmétodo de extensão. Então, parecia que eles eram os mesmos até que eu olhei mais de perto.

var q1 = 
    from n in N
    group n by n.MyKey into g
    select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>

O que equivale a:

var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>

Que se parece muito com:

var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>

Estou correto nos seguintes analogias?

  1. Um IGrouping<TKey, TVal>é um grupo único (isto é, uma sequência de chaveta), análogo ao KeyValuePair<TKey, TVal>onde o valor é, na verdade, uma sequência de elementos (em vez de um único elemento)
  2. Um IEnumerable<IGrouping<TKey, TVal>>é uma sequência daqueles (semelhante ao que você começa quando a iteração sobre umIDictionary<TKey, TVal>
  3. Uma ILookup<TKey, TVal>é mais como uma IDictionary<TKey, TVal>em que o valor é, na verdade, uma sequência de elementos
Publicado 26/08/2009 em 22:16
fonte usuário
Em outras línguas...                            


3 respostas

votos
64

Sim, todos aqueles estão corretas.

E ILookup<TKey, TValue>também se estende IEnumerable<IGrouping<TKey, TValue>>para que possa iterar sobre todos os pares de chave / cobrança, bem como (ou em vez de) simplesmente olhando para cima chaves particulares.

Basicamente, eu penso em ILookup<TKey,TValue>como sendo IDictionary<TKey, IEnumerable<TValue>>.

Tenha em mente que ToLookupé um "fazê-lo agora" operação (execução imediata), enquanto um GroupByé adiada. Como acontece, com a maneira que "puxar LINQ" funciona, quando você começar a puxar IGroupings do resultado de uma GroupBy, tem que ler todos os dados de qualquer maneira (porque você não pode mudar de grupo no meio), enquanto que em outras implementações for ser capaz de produzir um resultado streaming. (Ele faz em LINQ push, eu esperaria LINQ para Eventos de ser o mesmo.)

Respondeu 26/08/2009 em 22:21
fonte usuário

votos
8

Há outra diferença importante entre iLookup e IDictionary: o ex impõe imutabilidade no sentido de que aqui há métodos para alterar os dados (exceto quando o consumidor realiza uma conversão explícita). Por outro lado, IDictionary tem métodos como "Adicionar" que permitem alterar os dados. Assim, a partir da perspectiva de programação funcional e / ou programação paralela, iLookup é mais agradável. (Eu só desejo que houve também uma versão do iLookup que atribui apenas um valor a uma chave em vez de um grupo.)

(. Btw, parece importante ressaltar que a relação entre IEnumerable e IList é um pouco semelhante ao que entre iLookup e IDictionary - o primeiro é imutável, este último não é.)

Respondeu 05/06/2013 em 17:00
fonte usuário

votos
0

GroupBye ToLookUptem quase mesma funcionalidade EXCETO o seguinte: Referência

GroupBy: O operador GroupBy retorna grupos de elementos com base em algum valor chave. Cada grupo é representado por IGrouping objecto.

ToLookup: ToLookup é o mesmo que GroupBy; a única diferença é a execução de GroupBy é adiada enquanto execução ToLookup é imediata.

Deixa clara a diferença usando o código de exemplo. Suponha que temos uma classe representando Personmodelo:

class Personnel
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int Level { get; set; }
}

depois disso vamos definir uma lista de personnelscomo abaixo:

 var personnels = new List<Personnel>
    {
        new Personnel { Id = 1, FullName = "P1", Level = 1 },
        new Personnel { Id = 2, FullName = "P2", Level = 2 },
        new Personnel { Id = 3, FullName = "P3", Level = 1 },
        new Personnel { Id = 4, FullName = "P4", Level = 1 },
        new Personnel { Id = 5, FullName = "P5", Level =2 },
        new Personnel { Id = 6, FullName = "P6", Level = 2 },
        new Personnel { Id = 7, FullName = "P7", Level = 2 }
    };

Agora eu preciso para começar o personnelsagrupados por seu nível. Eu tenho dois abordagem aqui. usando GroupByou ToLookUp. Se eu usar GroupBy, como dito antes, ele irá usar execução adiada, isso significa que, quando você percorrer a coleção o próximo item pode ou não pode ser computado até que seja chamado para.

 var groups = personnels.GroupBy(p => p.Level);
    personnels.RemoveAll(p => p.Level == 1);
    foreach (var product in groups)
    {
        Console.WriteLine(product.Key);
        foreach (var item in product)
            Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level);
    }

No código acima, eu em primeiro lugar agrupados o personnels, mas antes de reiterar que, tirei alguns personnels. Como GroupByusa execução adiada, de modo que o resultado final não incluirá os itens removidos, porque o agrupamento será de computação no foreachponto aqui.

Saída:

2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2

Mas se eu reescrever o código acima como abaixo: (note que o código é o mesmo que o código anterior, exceto GroupByé substituído por ToLookUp)

 var groups = personnels.ToLookup(p => p.Level);
    personnels.RemoveAll(p => p.Level == 1);
    foreach (var product in groups)
    {
        Console.WriteLine(product.Key);
        foreach (var item in product)
            Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level);
    }

Como ToLookUpusa execução imediata, significa que, quando chama o ToLookUpmétodo, o resultado é gerado e grupo é aplicado, por isso, se remover qualquer item personnelsantes de iteração, que não vai afectar o resultado final.

Saída:

1
1 >>> P1 >>> 1
3 >>> P3 >>> 1
4 >>> P4 >>> 1
2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2

Nota: GroupBye ToLookUpretornam tipos diferentes também.

Você pode usar ToDictionary vez de ToLookup, mas você precisa prestar atenção a este :( referência )

O uso de ToLookup () é muito semelhante ao de ToDictionary (), ambos permitem que você especifique seletores chave, seletores de valor e comparadores. A principal diferença é que ToLookup () permite (e espera) as chaves duplicadas enquanto ToDictionary () não

Respondeu 08/08/2018 em 09:15
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more