удалить дубликаты данных в пользовательской структуре с помощью LINQ - PullRequest
0 голосов
/ 22 декабря 2018

Я хочу удалить дубликаты данных в пользовательской структуре с помощью LINQ.

Вот моя пользовательская структура:

enter image description here

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

Первая идея, которая приходит мне в голову, - это использование IEqualityComparer, но, похоже, он не может работать хорошо.

Если форма Aравный To of B и To of A равный From of B, который будет считаться дублирующими данными.

малый From будет сохранять, большой From удалит

Например, индекс 5сохранится, но индекс 6 будет удален.

Кто-нибудь знает, как решить эту проблему в LINQ?

Ответы [ 3 ]

0 голосов
/ 23 декабря 2018

Спасибо @Nicolas за идею, я думаю, что это лучший способ, что я могу получить.

listRow.Where(x => listRow.Any(y => x.From < y.From && x.From == y.To && x.To == y.From)).ToList();
0 голосов
/ 23 декабря 2018

Я собираюсь использовать Range вместо «пользовательской структуры»:

class Range
{
    public Range(int from, int to)
    {
        From = from;
        To = to;
    }

    public int From { get; }
    public int To { get; }
}

с использованием IEqualityComparer, но, похоже, не может хорошо работать.

Может быть, потому что "равенство" не может быть тривиально определено приравниванием одного (или обоих) Range свойств?Но вы (почти) прекрасно определяете равенство ...

x.From == y.To && x.To == y.From

Я думаю, что это должно быть исправлено ...

x.From == y.From && x.To == y.To

Кажется разумным, что два диапазона имеют равные Toи From равны.

Этого будет достаточно для реализации Equals метода IEqualityComparer.

Однако задача реализации GetHashCode всегда заключается в том, чтосовпадение с Equals методом - определенное здесь равенство должно приводить к идентичным хешам - но теперь оно основано на свойствах одного экземпляра объекта.

Первый импульс состоит в том, чтобы основать хеш на From + To.Но это сделало бы range(8,5) равным range(7,6).Эту проблему можно решить, введя From - To в уравнение.Два диапазона равны, когда From + To равен и , когда абсолютная разница From - To равна:

x.From + x.To == y.From  + y.To
    && Math.Abs( x.From - x.To) == Math.Abs(y.From  - y.To);

Это равенство, основанное на свойствах одного экземпляра с обеих сторонуравнения, так что теперь мы можем реализовать GetHashCode.Следуя рекомендациям (и помог Resharper):

public int GetHashCode(Range obj)
{
    var hashCode = -1781160927;
    hashCode = hashCode * -1521134295 + (obj.From + obj.To).GetHashCode();
    hashCode = hashCode * -1521134295 + (Math.Abs(obj.From - obj.To)).GetHashCode();
    return hashCode;
}

И полный компаратор:

class RangeEqualityComparer : IEqualityComparer<Range>
{
    public bool Equals(Range x, Range y)
    {
        return y != null
               && x != null
               && x.From + x.To == y.From  + y.To
               && Math.Abs( x.From - x.To) == Math.Abs(y.From  - y.To);
    }

    public int GetHashCode(Range obj)
    {
        var hashCode = -1781160927;
        hashCode = hashCode * -1521134295 + (obj.From + obj.To).GetHashCode();
        hashCode = hashCode * -1521134295 + (Math.Abs(obj.From - obj.To)).GetHashCode();
        return hashCode;
    }
}

Теперь вы получаете различные диапазоны ...

ranges.OrderBy(r => r.From).Distinct(new RangeEqualityComparer())

Порядок определяет, какой диапазон «равных» диапазонов появится в конечном результате.

0 голосов
/ 22 декабря 2018

Вы можете отфильтровать ваши данные с помощью linq, чтобы получить все дубликаты и впоследствии удалить их.

Мое решение, представленное ниже, может быть не самым умным, но попробуйте.

Это должно соответствоватьк вашим пользовательским данным (это помогло бы, если бы вы указали их в своем вопросе):

public class CustomStructure
{
    public int From { get; set; }
    public int To { get; set; }
    public int Sum { get { return From + To; } }
}

Где-то еще, где вы работаете с данными:

List<CustomStructure> customlist = GetCustomData();
IEnumerable<CustomStructure> dupes = customlist.Where(x => customlist.Any(y => x.From == y.To && x.To == y.From && x.From > y.From));

foreach (CustomStructure dupe in dupes)
{
    customlist.Remove(dupe);
}

Iу меня нет моей Visual Studio здесь, так что все это было написано без проверок;надеюсь, что это работает.

...