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

C# - Tuple or other multikey variant for Dictionary, but with permutability

我正在为以下问题绞尽脑汁。 我想创建一个字典,它使用多个键。我提出了建议将元组作为选择方法的解决方案。我认为这是一个很好的方法。但是我的问题有以下特点。我想制作钥匙 "permutable"(抱歉,如果我在这里使用了错误的俚语)。我的意思是,如下。我希望 dict[<key1,key2> 的结果与 dict[<key2,<key1>] 的结果相同,因为我要存储的数据对于键的顺序是不变的。

例如,请看下面的代码,目前当然不会产生我希望的结果。我希望置换键的结果与键元组的结果相同。

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

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

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

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

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

比较 List<string> 是否适合您的用例?如果是这样,我会推荐这个堆栈溢出分析器:

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

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