【发布时间】:2014-05-21 13:02:35
【问题描述】:
我有一个相同类型的对元组,例如:[1,1][1,2][2,1][2,1]
我需要计算不同的组合:[1,1][1,2]
public void DistinctPairsTest()
{
IList<Tuple<int, int>> pairs = new List<Tuple<int, int>>();
pairs.Add(Tuple.Create(1, 1));
pairs.Add(Tuple.Create(1, 2));
pairs.Add(Tuple.Create(2, 1));
pairs.Add(Tuple.Create(2, 1));
IList<Tuple<int, int>> distinctPairs = GetDistinctPairs(pairs);
Assert.AreEqual(2, distinctPairs.Count);
}
private IList<Tuple<T, T>> GetDistinctPairs<T>(IList<Tuple<T, T>> pairs)
{
throw new NotImplementedException();
}
您将如何实现通用 GetDistinctPairs(pairs) ?
解决方案:
正如 Heinzi 和 Dennis_E 建议的那样,我实现了一个通用的 IEqualityComparer。欢迎改进:-)
public class CombinationEqualityComparer<T> : IEqualityComparer<Tuple<T, T>>
{
public bool Equals(Tuple<T, T> x, Tuple<T, T> y)
{
bool equals = new HashSet<T>(new[] { x.Item1, x.Item2 }).SetEquals(new[] { y.Item1, y.Item2 });
return equals;
}
public int GetHashCode(Tuple<T, T> obj)
{
return obj.Item1.GetHashCode() + obj.Item2.GetHashCode();
}
}
【问题讨论】:
-
你可以让 Equals 更短: return (Equals(x.Item1, y.Item1) && Equals(x.Item2, y.Item2)) || (等于(x.Item1, y.Item2) && 等于(x.Item2, y.Item1))。我不是实现 GetHashCode() 的专家,但人们经常使用素数来乘以,否则 [a,b] 将始终给出与 [b,a] 相同的哈希码。所以,类似:return obj.Item1.GetHashCode() * 31 + obj.Item2.GetHashCode();
-
@Dennis_E:这是设计使然:在这种情况下,[a, b] 应该给出与 [b, a] 相同的哈希码,因为
Equals([a, b], [b, a])返回真的。 IEqualityComparer<T>.GetHashCode 的文档说:“需要实现以确保如果 Equals 方法为两个对象 x 和 y 返回 true,则 GetHashCode 方法为 x 返回的值必须等于为 y 返回的值。" -
当然! (拍了拍额头)
-
更短的实现是
return new HashSet<T>(new[] {x.Item1, x.Item2}).SetEquals(new[] {y.Item1, y.Item2});但是,这可能更适合代码高尔夫...... -
不错!我更新了解决方案