【问题标题】:Why doesn't Distinct (Linq) work in a List of int[]?为什么 Distinct (Linq) 在 int [] 列表中不起作用?
【发布时间】:2020-06-30 10:09:38
【问题描述】:

我写了这个方法。它应该从整数数组中返回所有三元组 [a, b, c],其中 a ^ 2 + b ^ 2 = c ^ 2。

public static List<int[]> AllTripletsThatFulfilla2b2c2Equality(int[] n)
    {
        var combinations = from i in n
                           from j in n
                           from p in n
                           select new int[][] {new int[]{ i, j, p }, new int[] {p, j, i}, new int[] {i, p, j}};
        
        return combinations.Where(x => x.Length == x.Distinct().Count() && Math.Pow(x[0], 2) + Math.Pow(x[1], 2) == Math.Pow(x[2], 2)).Distinct().ToList();
    }

distinct 不起作用。

我尝试了其他几种方法来写这个,包括

public static List<int[]> AllTripletsThatFulfilla2b2c2Equality(int[] n)
    {
        var combinations = from i in n
                           from j in n
                           from p in n
                           select new[] { i, j, p };
        combinations = combinations.ToList();
        Func<int[], List<int[]>> combo = x =>
        {
            List<int[]> list = new List<int[]>();
            list.Add(x);
            if (!combinations.Contains(new [] { x[0], x[2], x[1] }))
            {
                list.Add(new[] { x[0], x[2], x[1] });
            }


            if (!combinations.Contains(new[] { x[2], x[1], x[0] }))
            {
                list.Add(new[] { x[2], x[1], x[0] });
            }
            list.Add(new [] { x[0], x[2], x[1] });
            list.Add(new [] { x[2], x[1], x[0] });
            return list;
        };

        return combinations.SelectMany(combo).Distinct().Where(x => x.Length == x.Distinct().Count() && Math.Pow(x[0], 2) + Math.Pow(x[1], 2) == Math.Pow(x[2], 2)).ToList();
    }

甚至为 Distinct 添加了一个比较器:

        public class TripletComparer : IEqualityComparer<int[]>
    {
        public bool Equals(int[] x, int[] y)
        {
            return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
        }

        public int GetHashCode(int[] obj)
        {
            return obj.GetHashCode();
        }
    }

测试时结果相同,这个:

Assert.Equal() Failure
Expected: List<Int32[]> [[3, 4, 5], [4, 3, 5]]
Actual:   List<Int32[]> [[3, 4, 5], [3, 4, 5], [4, 3, 5], [4, 3, 5], [4, 3, 5], ...]

不知何故,它没有看到有重复的项目。有谁知道为什么以及如何解决它?

【问题讨论】:

  • 因为没有重载的比较和默认检查只有当它是同一个对象(内存中的同一个点)
  • @Selvin 好的,你知道如何解决吗?
  • 我的意思是您需要使用Distinct&lt;TSource&gt;(IEnumerable&lt;TSource&gt;, IEqualityComparer&lt;TSource&gt;) 并通过IEqualityComparer&lt;int[]&gt; 来指出当您说int[] 等于另一个int[] 时是什么意思
  • 查看副本,特别是这个答案,如果你不能(或不想)改变课程:stackoverflow.com/a/1365761/2528063
  • 你的GetHashCode-实现看起来很奇怪。通常,您会根据在实际 Equals-check 中使用的完全相同的成员计算哈希码。

标签: c# linq distinct


【解决方案1】:

您的GetHashCode-实现似乎很奇怪。通常,您会根据在实际Equals-check 中使用的完全相同的成员来计算哈希码。否则Distinct 可能甚至不会调用您的Equals 方法。

public bool Equals(int[] x, int[] y)
{
    return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
}

public int GetHashCode(int[] obj)
{
    int hash = 17;
    // Suitable nullity checks etc, of course :)
    hash = hash * 23 + obj[0].GetHashCode();
    hash = hash * 23 + obj[1].GetHashCode();
    hash = hash * 23 + obj[2].GetHashCode();
    return hash;
}

免责声明:hashcode-code 改编自https://stackoverflow.com/a/263416/2528063

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多