web-dev-qa-db-de.com

Unterschied zwischen Lookup () und Dictionary (Of list ())

Ich versuche mir zu überlegen, welche Datenstrukturen am effizientesten sind und wann/wo welche zu verwenden sind.

Es könnte nun sein, dass ich die Strukturen einfach nicht gut genug verstehe, aber wie unterscheidet sich eine ILookup(of key, ...) von einer Dictionary(of key, list(of ...))?

Auch wo würde ich ein ILookup verwenden wollen und wo wäre es effizienter in Bezug auf Programmgeschwindigkeit/Speicher/Datenzugriff usw.?

147
John Bustos

Zwei wesentliche Unterschiede:

  • Lookup ist unveränderlich. Ja :) (Zumindest glaube ich, dass die konkrete Klasse Lookup unveränderlich ist, und die Schnittstelle ILookup bietet keine mutierenden Elemente. Es gibt könnte andere mutierbare Elemente Implementierungen natürlich.)
  • Wenn Sie einen Schlüssel nachschlagen, der in einem Nachschlag nicht vorhanden ist, erhalten Sie eine leere Sequenz anstelle eines KeyNotFoundException zurück. (Daher gibt es kein TryGetValue, AFAICR.)

Ihre Effizienz ist wahrscheinlich gleich hoch - die Suche könnte beispielsweise hinter den Kulissen einen Dictionary<TKey, GroupingImplementation<TValue>> Verwenden. Wählen Sie je nach Ihren Anforderungen aus. Persönlich finde ich, dass das Nachschlagen normalerweise besser passt als ein Dictionary<TKey, List<TValue>>, Hauptsächlich aufgrund der ersten beiden obigen Punkte.

Beachten Sie, dass als Implementierungsdetail die konkrete Implementierung von IGrouping<,>, Die für die Werte verwendet wird, IList<TValue> Implementiert, was bedeutet, dass die Verwendung mit Count(), ElementAt() etc.

229
Jon Skeet

Interessant, dass niemand den tatsächlich größten Unterschied angegeben hat (direkt entnommen aus MSDN ):

Eine Suche ähnelt einem Wörterbuch. Der Unterschied besteht darin, dass ein Dictionary Schlüssel einzelnen Werten zuordnet, während ein Lookup Schlüssel Sammlungen von Werten zuordnet.

35

Sowohl ein Dictionary<Key, List<Value>> Als auch ein Lookup<Key, Value> Können logischerweise Daten enthalten, die auf ähnliche Weise organisiert sind, und beide weisen dieselbe Effizienzordnung auf. Der Hauptunterschied ist, dass ein Lookup unveränderlich ist: Es hat keine Add() -Methoden und keinen öffentlichen Konstruktor (und wie Jon erwähnt hat, können Sie einen nicht vorhandenen Schlüssel ohne Ausnahme abfragen und den Schlüssel als haben Teil der Gruppierung).

Was Sie verwenden, hängt wirklich davon ab, wie Sie sie verwenden möchten. Wenn Sie eine Zuordnung von Schlüsseln zu mehreren Werten pflegen, die ständig geändert wird, ist ein Dictionary<Key, List<Value>> Wahrscheinlich besser, da es veränderbar ist.

Wenn Sie jedoch über eine Datensequenz verfügen und nur eine schreibgeschützte Ansicht der nach Schlüsseln geordneten Daten wünschen, ist eine Suche sehr einfach zu erstellen und bietet einen schreibgeschützten Schnappschuss.

32

Der Hauptunterschied zwischen einem ILookup<K,V> und ein Dictionary<K, List<V>> ist, dass ein Wörterbuch veränderlich ist; Sie können Schlüssel hinzufügen oder entfernen sowie Elemente zu der nachgeschlagenen Liste hinzufügen oder daraus entfernen. Ein ILookup ist nveränderlich und kann nach seiner Erstellung nicht mehr geändert werden.

Die zugrunde liegende Implementierung beider Mechanismen ist entweder gleich oder ähnlich, sodass die Suchgeschwindigkeit und der Speicherbedarf ungefähr gleich sind.

11
Servy

Ein weiterer, noch nicht erwähnter Unterschied ist, dass Lookup () nterstützt Null-Schlüssel :

Die Lookup-Klasse implementiert die ILookup-Schnittstelle. Die Suche ist einem Wörterbuch sehr ähnlich, mit der Ausnahme, dass mehrere Werte demselben Schlüssel zugeordnet werden dürfen und Nullschlüssel unterstützt werden.

9

Wenn eine Ausnahme nicht möglich ist, suchen Sie nach

Wenn Sie versuchen, eine Struktur zu erhalten, die so effizient ist wie ein Dictionary, aber nicht sicher sind, dass die Eingabe keinen doppelten Schlüssel enthält, ist Lookup sicherer.

Wie bereits in einer anderen Antwort erwähnt, werden auch Null-Schlüssel unterstützt. Bei Abfragen mit beliebigen Daten wird immer ein gültiges Ergebnis zurückgegeben, sodass unbekannten Eingaben mehr Widerstand geboten wird (weniger anfällig für Ausnahmen als bei Dictionary).

Dies gilt insbesondere dann, wenn Sie es mit der Funktion System.Linq.Enumerable.ToDictionary Vergleichen:

// 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);

Die Alternative wäre, einen eigenen doppelten Schlüsselverwaltungscode in eine foreach -Schleife zu schreiben.

Leistungsüberlegungen, Wörterbuch: ein klarer Gewinner

Wenn Sie keine Liste benötigen und eine große Anzahl von Elementen verwalten möchten, ist Dictionary (oder sogar Ihre eigene maßgeschneiderte Struktur) effizienter:

        Stopwatch stopwatch = new Stopwatch();
        var list = new List<string>();
        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);
        // ...

Da Lookup für jeden Schlüssel eine Liste mit Elementen führen muss, ist diese langsamer als Dictionary (bei einer großen Anzahl von Elementen ist sie etwa 3x langsamer).

Suchgeschwindigkeit: Erstellung: 00: 00: 01.5760444

Wörterbuchgeschwindigkeit: Erstellung: 00: 00: 00.4418833

4
Fab