Страницы

Поиск по вопросам

пятница, 14 февраля 2020 г.

Сравнить два списка и убрать совпадающие элементы

#c_sharp


Есть два условных класса:

public class One{
    public string Common {get;set;}
    ...}
public class Two{
    public string Common {get;set;}
    ...}


В данном примере показана одна переменная в каждом классе, она будет содержать одинаковые
значения. Кроме этой переменной в каждом классе будет по 5 других, которые имеют разные,
никак несвязанные значения.
Есть списки:

List ListOne = new List();
List ListTwo = new List():


Необходимо сравнить эти 2 списка, и убрать из них те элементы, у которых переменная
Common совпадает (т.е. есть элементы в разных списках, у которых одинакова эта переменная).

На ум приходит только foreach, завернутый в другой foreach, но это перебор достаточного
большого числа вариантов (в каждом списке будет около 50-ти элементов), есть ли более
оптимизированный подход?
    


Ответы

Ответ 1



Можно вот так, но все равно "за кулисами" выполняются циклы: List ListOne = new List(); List ListTwo = new List(); var result=ListOne.Join(ListTwo,ok=>ok.Common,ik=>ik.Common,(one,two)=>new {one,two}).ToList(); ListOne.RemoveAll(x=>result.Any(r => x==r.one)); ListTwo.RemoveAll(x=>result.Any(r => x==r.two)); P.S Есть еще вариант написать кастомный EqualityComparer для object'ов. Внутри приводить к нужному типу и выполнять сравнение. Затем идти циклом и добавлять в этот HashSet значения поочередно. Если оно не было добавлено, значит пересечении => удаляем элемент из исходных коллекций. Правда, не знаю, на сколько это будет быстрее. В теории должно.

Ответ 2



Еще вариант: var commons = ListOne.Select(o => o.Common).Intersect(ListTwo.Select(t => t.Common)).ToList(); // Тут, скорее всего, лучше будет вместо `ToList()` использовать // `.ToHashSet()` если используется .NET 4.7.2+ или .NET Core 2.0+, // либо `ToDictionary(x => x)` для более старых версий ListOne.RemoveAll(o => commons.Contains(o.Common)); ListTwo.RemoveAll(t => commons.Contains(t.Common)); Внутри Intersect используется хэш-таблица, поэтому должно работать быстрее. Ну и не создаем лишних экземпляров анонимного класса.

Ответ 3



Вариант с hashset-ом дублируемых "ключей" var dublicateKeys = new HashSet(ListOne.Where(x => ListTwo.Exists(y => y.Common == x.Common)).Select(x => x.Common)); ListOne.RemoveAll(x => dublicateKeys.Contains(x.Common)); ListTwo.RemoveAll(x => dublicateKeys.Contains(x.Common));

Комментариев нет:

Отправить комментарий