如何在C# / LINQ中获取所有不同的配对组合?

9

我有一组由相同类型的对组成的元组,例如:[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)) || (Equals(x.Item1, y.Item2) && Equals(x.Item2, y.Item1))。我不是 GetHashCode() 实现的专家,但人们经常使用质数来将其中一个数字与之相乘,否则 [a,b] 将始终给出与 [b,a] 相同的哈希码。因此,可以尝试以下代码:return obj.Item1.GetHashCode() * 31 + obj.Item2.GetHashCode(); - Dennis_E
1
@Dennis_E:这是设计上的考虑:在这种情况下,[a,b]应该给出与[b,a]相同的哈希码,因为Equals([a,b],[b,a])返回true。IEqualityComparer<T>.GetHashCode的文档中说:“* 实现必须确保如果Equals方法为两个对象x和y返回true,则对于x返回的GetHashCode方法的值必须等于为y返回的值。*" - Heinzi
当然!(拍了拍额头) - Dennis_E
一个更短的实现方式是 return new HashSet<T>(new[] {x.Item1, x.Item2}).SetEquals(new[] {y.Item1, y.Item2}); 然而,这可能更适合于代码高尔夫比赛... - Heinzi
很好!我更新了解决方案。 - mamuesstack
2个回答

11

有一个Enumerable.Distinct重载可以让你指定一个IEqualityComparer

提供一个自定义的IEqualityComparer<Tuple<T, T>>,将[1, 2]和[2, 1]视为相等。

实现应该很简单,留给读者作为练习。 :-)


太棒了!谢谢你的回答! - mamuesstack

5

您可以编写一个实现IEqualityComparer<Tuple<int, int>>接口的类,并在调用Distinct()方法时使用它:

pairs.Distinct(new YourComparerClass());

谢谢。不幸的是,@Heinzi更准确一些(尽管几乎是完全相同的答案)。 - mamuesstack
好的,我们恰巧同时回答了(经常发生)。 - Dennis_E

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接