Zwei Zeichenfolgen für den Schlüssel eines Wörterbuchs

8

Ich habe zwei Strings, die ich gerne als Dictionary-Schlüssel verwenden würde, aber ich bin irgendwie faul, ein anderes Objekt zu erstellen, den Hash-Code der Strings usw. zu berechnen.

Also kann ich statt dessen die Hashcodes von zwei Strings bekommen, sie addieren und das Ergebnis als Schlüssel des Dictionary verwenden?

Es ist möglich, Kollisionen zu verursachen? richtig?.

Irgendwelche Ideen?

    
DarthVader 20.02.2011, 20:26
quelle

4 Antworten

19
  

Ich habe zwei Saiten, die ich gerne hätte   Verwenden Sie sie als Wörterbuchschlüssel, aber ich bin   irgendwie faul, ein anderes Objekt zu erstellen

In .NET 4.0 können Sie die Tuple<T1, T2> Klasse als Schlüssel, mit T1 und T2 = String.

  

kann ich die Hashcodes von zwei Saiten bekommen   füge sie hinzu und verwende das Ergebnis als   Schlüssel des Wörterbuchs?

Die Formel Tuple<T1, T2> verwendet für die Kombination von Hash-Codes ist etwas wie (nicht dokumentiert oder garantiert, nicht zu ändern): ((h1 << 5) + h1) ^ h2 , die für Ihre Zwecke anständig genug sein sollte. Übrigens ist das naive Hinzufügen normalerweise nicht die beste Art, Hash-Codes zu kombinieren.

  

Es ist möglich, Kollisionen zu verursachen?   richtig?.

Dies ist immer möglich, sogar mit einer einzelnen Zeichenkette. Es gibt mehr Zeichenfolgen als 32-Bit-Ganzzahlen.

    
Ani 20.02.2011, 20:29
quelle
10

Wenn Sie .NET 4 verwenden, können Sie die Klasse Tuple verwenden:

%Vor%

Wenn Sie nicht in .NET 4 sind, sollten Sie Ihren eigenen Typ erstellen, um dies zu speichern.

Sie können die KeyValuePair -Struktur verwenden, aber sie erbt die relevanten Methoden vom Basiswert Typ, und beruht somit stark auf Reflexion. Dies hat Auswirkungen auf die Leistung (siehe unten in der Antwort).

Für KeyValuePair:

%Vor%

Hier ist ein allgemeiner Typ, den Sie verwenden können, wenn Sie nicht selbst kochen möchten:

%Vor%

Natürlich funktioniert KeyValuePair auch unter .NET 4.0 genauso wie gut schlecht.

Wie bei Kollisionen hängt es davon ab, was Sie meinen. Eine Hashtabelle (ein Wörterbuch verwendet intern eine Hashtabellenstruktur) hat immer die Möglichkeit, Schlüsselkollisionen zu bekommen, aber hier kommt der Vergleich ins Spiel. Wenn zwei verschiedene Schlüssel denselben Hash-Code generieren, vergleicht die Wörterbuchklasse Schlüssel mit Schlüssel, um zu sehen, ob sie wirklich die gleichen Werte haben, oder produziert nur den gleichen Hash-Code.

Die Gründe dafür, dass eine Hashtabelle immer die Möglichkeit von Kollisionen haben wird, lassen sich am besten mit dem Taubenschlag-Prinzip (Wikipedia) beschreiben .

Das bedeutet, dass wenn zwei verschiedene Schlüssel eine Kollision verursachen würden, dies kein Problem wäre, sie werden beide mit den richtigen Werten im Wörterbuch gespeichert.

Wenn Sie denselben Schlüssel zweimal erstellen, zählt das Wörterbuch den gleichen Schlüssel und fügt entweder keinen neuen Wert hinzu oder überschreibt den vorhandenen (je nachdem, wie Sie den Wert hinzufügen möchten.)

Dies wird eine Ausnahme für doppelte Schlüssel auslösen:

%Vor%

Dies wird hinzufügen oder überschreiben bestehende:

%Vor%

Als Antwort auf den Kommentar von Ani habe ich das folgende einfache Testskript für LINQPad geschrieben. Die Ausgabe war:

%Vor%

Skript:

%Vor%     
quelle
3

Benutze ein Tupel:

%Vor%     
mancaus 20.02.2011 20:29
quelle
3

Einfache Lösung, die mit allen Versionen von .net funktioniert. Verketten Sie die Saiten einfach miteinander.

%Vor%

Natürlich funktioniert das nur mit 2 Strings (obwohl Sie .ToString () bei vielen anderen Typen verwenden könnten) und wenn Sie das Wörterbuch nicht nur mit einer der beiden Strings suchen müssen, aber wenn Sie beides haben ganz einfach.

    
Erik Funkenbusch 20.02.2011 20:35
quelle