与List <list <double >>不同

时间:2018-07-17 18:42:55

标签: c# distinct-values

genesUsingCrossover是List<List<double>>

我正在使用以下代码行来计算List<double>中不同的List<List<double>>

int count = genesUsingCrossover.Distinct().Count();

,我不确定这是正确的。 genesUsingCrossover中的元素数为1250,并且genesUsingCrossover.Distinct().Count()返回1250,因此我假设它们都是不同的List。但是,在观察窗口中,我注意到第三和第四列表是相同的。

因此,我认为代码行不正确。有办法改善吗?并计算不同元素的数量?

enter image description here

3 个答案:

答案 0 :(得分:3)

List<T>不会覆盖Object.Equals,因此两个List<double>对象只有在引用相等时才被视为相等。 (HereDistinct<T>()的实现,如果您想看看它是如何工作的。)听起来好像您希望两个列表相等(如果组成它们的元素相等)。为此,您可以使用带有IEqualityComparer<T>的{​​{3}},它将用来确定两个列表是否相等。因此,在您的情况下,您可以提供IEqualityComparer<List<double>>的实现,以表达您的列表平等思想。

该实现的外观取决于您何时希望两个列表相等。例如,它们必须具有相同顺序的相同元素集,还是顺序不相关?关于堆栈溢出还有其他问题可以解释如何实现这两个问题。在任何一种情况下,请记住Distinct()将多次调用您的实现,因此,算法必须具有良好的性能,这一点很重要。为此,可能值得问一问List<List<double>>是否真的是您想要的数据结构,或者其他选择是否更适合。

答案 1 :(得分:1)

实际上,您没有定义两个列表被视为相等的条件。 这意味着.NET默认检查两个列表在内存中是否具有相同的引用,因为Listreference type

很显然,每个列表都有他的记忆。因此,您的列表包含1205个元素,它返回的1205个元素与众不同。

作为您的描述,我认为您的标准是:2个包含相同元素的列表应该相等。

Distinct可以收到IEqualityComparer,所以这个想法是:为IEqualityComparer实现List<double>

class NumberDoubles: IEqualityComparer<List<double>>
{
    public bool Equals(List<double> x, List<double> y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        if (x.Count!= y.Count)
            return false;

        //Check whether the arrays' values are equal.
        for(int i = 0; i < x.Count; i++){
            if(x[i] != y[i])
                return false;
        }

        // If got this far, arrays are equal
        return true;
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public int GetHashCode(List<double> doubleArray)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(doubleArray, null)) return 0;

        //Calculate the hash code for the array
        int hashCode = 0;
        bool isFirst = true;
        foreach(int i in doubleArray){
            if(isFirst) {
                hashCode = i;
                isFirst = false;
            }
            else
            {
                hashCode = hashCode ^ i;
            }
        }
        return hashCode;
    }
}

和您的代码:

genesUsingCrossover.Distinct(new NumberDoubles());

答案 2 :(得分:0)

就像@Joe所说,您应该真的在想:“我真的需要List<List<double>>听起来对我来说是不合适的结构。HashSet可以与众不同(不是吗?完全取决于您的情况,但是通常每次有人看到HashSet时,它都会发出希望唯一的提示,而List<List<double>>不一定会表明这一点。

话虽如此,我建议您使用HashSet<List<double>>

以下解决方案
using System;
using System.Collections.Generic;
using System.Linq;

public static class Program {
    public static void Main() {
        var hashSet = new HashSet<List<double>>(new ListComparer());

        hashSet.Add(new List<double> { 1.2d, 1.5d });
        hashSet.Add(new List<double> { 1.2d, 1.5d });

        Console.Write(hashSet.Count);
    }

    public class ListComparer : IEqualityComparer<List<double>> 

    {
        public bool Equals(List<double> x, List<double> y)
        {
            // your logic for equality
            return true;
        }

        public int GetHashCode(List<double> obj)
        {
           int hash = 0;
           unchecked {
               foreach(var d in obj) {
                   hash += d.GetHashCode();
               }
           }
           return hash;
        }  
    }
}

请记住,Equals方法将被调用很多次,因此,考虑到一些性能方面的考虑可能会很好。