Differenza tra Lookup () e Dictionary (Of list ())

Sto cercando di capire quali sono le strutture dati più efficienti e quando / dove usare quelle.

Ora, potrebbe essere che semplicemente non capisco abbastanza bene le strutture, ma come è un ILookup(of key, ...) diverso da un Dictionary(of key, list(of ...)) ?

Anche dove vorrei usare un ILookup e dove sarebbe più efficiente in termini di velocità di programma / accesso alla memoria / dati, ecc.?

Due differenze significative:

  • Lookup è immutabile. Sì (almeno credo che la class di Lookup concreta sia immutabile e l’interfaccia di ILookup non fornisce alcun membro mutante. Ovviamente potrebbero esserci altre implementazioni mutevoli).
  • Quando si cerca una chiave che non è presente in una ricerca, si ottiene una sequenza vuota anziché una KeyNotFoundException . (Quindi non c’è TryGetValue , AFAICR.)

È probabile che siano equivalenti in termini di efficienza: la ricerca potrebbe utilizzare un Dictionary> dietro le quinte, ad esempio. Scegli tra loro in base alle tue esigenze. Personalmente trovo che la ricerca sia di solito migliore di un Dictionary> , principalmente per i primi due punti sopra.

Si noti che come un dettaglio di implementazione, l’implementazione concreta di IGrouping<,> che viene utilizzata per i valori implementa IList , il che significa che è efficiente da usare con Count() , ElementAt() ecc.

Interessante che nessuno abbia dichiarato la differenza più grande (presa direttamente da MSDN ):

Una ricerca è simile a un dizionario. La differenza è che un dizionario mappa le chiavi su valori singoli, mentre una ricerca mappa le chiavi in ​​raccolte di valori.

Sia un Dictionary> che una Lookup possono contenere logicamente i dati organizzati in modo simile ed entrambi sono dello stesso ordine di efficienza. La differenza principale è che una ricerca è immutabile: non ha metodi Add() e nessun costruttore pubblico (e, come menzionato da Jon, puoi interrogare una chiave inesistente senza un’eccezione e avere la chiave come parte del raggruppamento).

Per quanto riguarda ciò che usi, dipende molto da come vuoi usarli. Se stai mantenendo una mappa di chiavi su più valori che vengono costantemente modificati, allora un Dictionary> è probabilmente migliore poiché è mutabile.

Se, tuttavia, si dispone di una sequenza di dati e si desidera solo una visualizzazione di sola lettura dei dati organizzati per chiave, una ricerca è molto semplice da build e offre un’istantanea di sola lettura.

La differenza principale tra un ILookup e un Dictionary> è che un dizionario è mutabile; puoi aggiungere o rimuovere le chiavi e anche aggiungere o rimuovere elementi dall’elenco che è stato cercato. Un ILookup è immutabile e non può essere modificato una volta creato.

L’implementazione sottostante di entrambi i meccanismi sarà uguale o simile, quindi la loro velocità di ricerca e il loro impatto sulla memoria saranno approssimativamente uguali.

Un’altra differenza non menzionata ancora è che Lookup () supporta chiavi null :

La class Lookup implementa l’interfaccia ILookup. La ricerca è molto simile a un dizionario, tranne che a più valori è consentito mappare sulla stessa chiave e sono supportate le chiavi null.

Quando l’eccezione non è un’opzione, vai a Ricerca

Se stai cercando di ottenere una struttura efficiente come un Dictionary ma non sai per certo che non ci sono chiavi duplicate in input, la ricerca è più sicura.

Come menzionato in un’altra risposta, supporta anche le chiavi null e restituisce sempre un risultato valido quando interrogato con dati arbitrari, quindi appare più resiliente all’input sconosciuto (meno incline del dizionario per aumentare le eccezioni).

Ed è particolarmente vero se lo si confronta con la funzione System.Linq.Enumerable.ToDictionary :

 // won't throw new[] { 1, 1 }.ToLookup(x => x); // System.ArgumentException: An item with the same key has already been added. new[] { 1, 1 }.ToDictionary(x => x); 

L’alternativa sarebbe scrivere il proprio codice di gestione delle chiavi duplicato all’interno di un ciclo foreach .

Considerazioni sulle prestazioni, Dizionario: un chiaro vincitore

Se non hai bisogno di un elenco e gestirai un numero enorme di elementi, il Dictionary (o anche la tua struttura personalizzata su misura) sarebbe più efficiente:

  Stopwatch stopwatch = new Stopwatch(); var list = new List(); for (int i = 0; i < 5000000; ++i) { list.Add(i.ToString()); } stopwatch.Start(); var lookup = list.ToLookup(x => x); stopwatch.Stop(); Console.WriteLine("Creation: " + stopwatch.Elapsed); // ... Same but for ToDictionary var lookup = list.ToDictionary(x => x); // ... 

Poiché Lookup deve mantenere un elenco di elementi per ogni chiave, è più lento del dizionario (circa 3 volte più lento per un numero enorme di elementi)

Velocità di ricerca: Creazione: 00: 00: 01.5760444

Velocità del dizionario: Creazione: 00: 00: 00.4418833