C# - 字典的元组或其他多键变体,但具有可置换性

时间:2016-04-15 20:09:55

标签: c# dictionary key tuples

我对以下问题感到头疼。 我想创建一个使用多个键的字典。我提出了解决方案,建议将元组作为首选方法。我认为这是一个很好的方式。但是我的问题有以下特点。我想制作钥匙&#34; permutable&#34; (对不起,如果我在这里使用错误的俚语)。我的意思是以下几点。我希望dict[<key1,key2>的结果与dict[<key2,<key1>]的结果相同,因为我要存储的数据对于键的顺序是不变的。

作为一个例子,请参阅以下代码,当然这不会产生我希望得到的结果。我希望使用置换键的结果与key-tuple相同。

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

所有这一切的原因,我必须存储数据,必须用两个键索引,但基本上是对称的。因此没有必要存储两次。

3 个答案:

答案 0 :(得分:3)

您可以定义自己的自定义相等比较器并在字典中使用它:

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();
    }
}

然后,您可以创建字典,并将其传递给比较器的实例:

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

答案 1 :(得分:2)

您需要使用两个元素定义自己的类,并实现IComparable,其中CompareTo将根据您的要求编写。然后使用该类作为您的词典的键。另外,请覆盖方法GetHashCode。

答案 2 :(得分:0)

比较List<string>是否适用于您的用例?如果是这样,我建议这个堆栈溢出anser:

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

如果你不能使用List<string>,那么我同意rbaghbanli的回答。