2016-04-15 6 views
1

Ich kratze mich über das folgende Problem. Ich möchte ein Wörterbuch erstellen, das mehrere Schlüssel verwendet. Ich kam zu den Lösungen, die Tupel als Methode der Wahl vorschlagen. Ich denke, das ist ein guter Weg. Jedoch hat mein Problem die folgende Spezialität. Ich möchte die Schlüssel "permutabel" machen (Sorry, wenn ich hier den falschen Slang benutze). Was ich damit meine, ist folgendes. Ich möchte, dass das Ergebnis dict[<key1,key2> dasselbe ist wie mit dict[<key2,<key1>], weil die Daten, die ich speichern möchte, in der Reihenfolge der Schlüssel invariant sind.C# - Tupel oder andere multikey Variante für Dictionary, aber mit Permutabilität

Als Beispiel siehe den folgenden Code, der im Moment natürlich nicht das erhoffte Ergebnis liefert. Ich möchte, dass das Ergebnis mit dem permutierten Schlüssel dem Schlüssel-Tupel entspricht.

Tuple<string, string> key = new Tuple<string, string>("Name1", "Name2"); 
    Dictionary<Tuple<string,string>, double> dict = new Dictionary<Tuple<string, string>, double>(); 
    dict.Add(key, 5.0); 

    Console.WriteLine(dict[key]); 

    Tuple<string, string> permutedKey = new Tuple<string, string>("Name2", "Name1"); 
    Console.WriteLine(dict[permutedKey]); 

Der Grund für all dies, ich habe Daten zu speichern, die mit zwei Schlüsseln indiziert werden muss, ist aber im Grunde immer symetrisch. Es besteht also keine Notwendigkeit, es zweimal zu speichern.

Antwort

3

Sie können eigenen Gleichheitsvergleich definieren und im Wörterbuch verwenden:

class TupleComparer<T> : IEqualityComparer<Tuple<T, T>> 
{ 
    public bool Equals(Tuple<T, T> x, Tuple<T, T> y) 
    { 
     return object.Equals(x.Item1, y.Item1) && object.Equals(x.Item2, y.Item2) || 
       object.Equals(x.Item1, y.Item2) && object.Equals(x.Item2, y.Item1); 
    } 

    public int GetHashCode(Tuple<T, T> obj) 
    { 
     return obj.Item1.GetHashCode() + obj.Item2.GetHashCode(); 
    } 
} 

Dann können Sie das Wörterbuch erstellen sie eine Instanz des comparer vorbei:

Tuple<string, string> key = new Tuple<string, string>("Name1", "Name2"); 

Dictionary<Tuple<string,string>, double> dict = 
    new Dictionary<Tuple<string, string>, double>(new TupleComparer<string>()); 

dict.Add(key, 5.0); 
Console.WriteLine(dict[key]); 

var permutedKey = new Tuple<string, string>("Name2", "Name1"); 
Console.WriteLine(dict[permutedKey]); 
+0

Vielen Dank. Ich bin ernsthaft beeindruckt, wie schnell du mir helfen kannst. Leider habe ich nicht den Ruf, deine Antwort zu verbessern. Aber vielen Dank trotzdem. Es funktioniert einwandfrei. – Johannes

+0

@Johannes du bist willkommen, wenn diese Antwort dir hilft, bitte bedenke es als akzeptiert, danke;) –

2

Sie müssen Ihre eigene Klasse mit zwei Elementen definieren und IComparable implementieren, wobei CompareTo gemäß Ihren Anforderungen geschrieben wird. Verwenden Sie diese Klasse dann als Schlüssel für Ihr Wörterbuch. Bitte überschreiben Sie auch die Methode GetHashCode.

0

vergleicht List<string> eine praktikable Option für Ihren Anwendungsfall? Wenn ja, würde ich diesen Stack-Überlauf Anser empfehlen:

Compare two List<T> objects for equality, ignoring order

Wenn Sie nicht List<string> verwenden können, dann würde ich mit rbaghbanli Antwort zustimmen.