Remove Duplicate Items from a List Containing a Cl

2020-04-14 09:00发布

问题:

I've got a list containing objects from a class. The class which contains various items including int and double arrays. The class looks something like this.

public class NewChildren
{
    public double[] fitnessValue{get;set;}

    public int[] locationScheme{get;set;}

    public double crowdingDistance{get;set;}
}

As the list might contain duplicate items, I'm interested in removing them. On the web, I've seen some solutions based on Linq which use Distinct() and GroupBy() methods. However, it seems that these methods won't work as there is arrays in objects (the MSVS2008 won't give any error, but no item is removed either).

Any suggestion (including references or codes) is highly appreciated. Thanks in advance.

回答1:

The question you must ask yourself is, when two instances of NewChildren are the same? Since you have lists there, this may not be an easy question to answer. When you have defined this, you must implement the equality method in your class:

public class NewChildren
{
    public double[] fitnessValue{get;set;}

    public int[] locationScheme{get;set;}

    public double crowdingDistance{get;set;}

    public bool override Equals(object other)
    {
        // ... implement your rules for equality here
    }
}

Now, to do so, you must always follow Microsoft guidelines. Overriding equality is not that simple, although it's not complex. As an example, where you'd have all arrays with the same elements:

public bool override Equals(object other)
{
    if (other == null || !(other is NewChildren)) 
    {
        return false;
    }

    var another = (NewChildren)other;

    return AreEquivalent(this.fitnessValue, another.fitnessValue)
        && AreEquivalent(this.locationScheme, another.locationScheme)
        && AreEquivalent(this.crowdingDistance, another.crowdingDistance);

}

public static bool AreEquivalent<T>(T[] a, T[] b)
{
    return a1.OrderBy(a => a).SequenceEqual(a2.OrderBy(a => a));
}

The implementation of array equality was taken from here. You can optimize it using this reference.



回答2:

As stated in the docs, Distinct uses the default equality comparer by default. That default equality comparer recognizes each of the items in your list as distinct from all others because it checks on instance identity.

As stated in the aforementioned docs, in order to compare a custom type and define equality like you want, you will need to implement some comparison-related methods on your class:

To compare a custom data type, you need to implement [IEquatable<T>] and provide your own GetHashCode and Equals methods for the type.



回答3:

The Equals method and equal operator for objects that are created from a class are evaluated by checking reference equality by default. That means that two items are equal only if they reference the same instance of a class. You'll either need to change your query to check the individual properties inside the class or implement overrides of the appropriate methods and operators.

See the following on MSDN:

  • Guidelines for Implementing Equals and the Equality Operator (==)
  • IEquatable Interface