Удаление повторяющихся элементов из списка, содержащего класс с элементами массива

У меня есть список, содержащий объекты из класса. Класс, который содержит различные элементы, включая массивы int и double. Класс выглядит примерно так.

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

    public int[] locationScheme{get;set;}

    public double crowdingDistance{get;set;}
}

Поскольку список может содержать повторяющиеся элементы, я заинтересован в их удалении. В Интернете я видел несколько решений, основанных на Linq, которые используют методы Distinct() и GroupBy(). Однако похоже, что эти методы не будут работать, так как в объектах есть массивы (MSVS2008 не выдает никакой ошибки, но и элемент не удаляется).

Любое предложение (включая ссылки или коды) высоко ценится. Заранее спасибо.


person Ehsan    schedule 17.09.2012    source источник


Ответы (3)


Вы должны задать себе вопрос: когда два экземпляра NewChildren совпадают? Поскольку у вас есть списки, ответить на этот вопрос может быть непросто. Когда вы определили это, вы должны реализовать метод равенства в своем классе:

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
    }
}

Теперь для этого вы всегда должны следовать Рекомендации Microsoft. Переопределить равенство не так уж просто, хотя и не сложно. В качестве примера, где у вас будут все массивы с одинаковыми элементами:

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));
}

Реализация равенства массивов была взята из здесь. Вы можете оптимизировать его, используя эту ссылку.

person Bruno Brant    schedule 17.09.2012
comment
Спасибо. Ваш простой пример кодирования метода Equals направил меня в правильном направлении и решил мою проблему. - person Ehsan; 18.09.2012
comment
@Эхсан, нет проблем! Я здесь, чтобы помочь. Только не забудьте следовать рекомендациям Microsoft и переопределить GetHashCode. Вы также можете переопределить operator== (просто делегируйте Equals). - person Bruno Brant; 19.09.2012

Как указано в документах, Distinct по умолчанию использует компаратор проверки на равенство. Этот компаратор равенства по умолчанию распознает каждый из элементов в вашем списке как отличный от всех остальных, потому что он проверяет идентичность экземпляра.

Как указано в вышеупомянутых документах, чтобы сравнить пользовательский тип и определить равенство, как вы хотите, вам нужно будет реализовать некоторые методы, связанные со сравнением, в вашем классе:

Для сравнения пользовательского типа данных необходимо реализовать [IEquatable<T>] и укажите собственные GetHashCode и Equals для типа.

person O. R. Mapper    schedule 17.09.2012

Метод Equals и оператор равенства для объектов, созданных из класса, по умолчанию оцениваются путем проверки равенства ссылок. Это означает, что два элемента равны, только если они ссылаются на один и тот же экземпляр класса. Вам нужно либо изменить свой запрос, чтобы проверить отдельные свойства внутри класса, либо реализовать переопределение соответствующих методов и операторов.

См. следующее в MSDN:

person JamieSee    schedule 17.09.2012
comment
Спасибо за разъяснения и ссылки. - person Ehsan; 18.09.2012