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的回答。
我正在为以下问题绞尽脑汁。
我想创建一个字典,它使用多个键。我提出了建议将元组作为选择方法的解决方案。我认为这是一个很好的方法。但是我的问题有以下特点。我想制作钥匙 "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的回答。