Предположим, что у меня есть List<Product>
именем big
of some object Product
который имеет 2 поля, ID
и Name
. Список полностью заполнен, что означает, что каждый элемент имеет оба поля не null
, хотя они могут быть.
У меня есть другой List<Product>
, меньший, чем первый, с именем small
, но на этот раз поле Name
имеет значение null
для некоторых элементов, тогда как ID
всегда присутствует.
Я хочу удалить small
из big
где ID
- то же самое.
Пример:
List<Product> big = { {1,A},{2,B},{3,C},{4,D} };
List<Product> small = { {1,null},{3,C} };
List<Product> result = { {2,B},{4,D}};
Я не могу изменить объект Product
, т. IEquatable<Product>
Я не могу реализовать IEquatable<Product>
, и такой интерфейс не реализован, что означает, что big.Except(small)
или big.RemoveAll(small)
или big.Contains(anElementOfSmall)
не будет работать (ради вопроса, я пробовал их).
Я хочу избежать двойного цикла с удалением итератора или аналогичным, я ищу встроенные функции с конкретными предикатами.
Внедрите IEqualityComparer
для вашего продукта, который сравнивает два Product
на основе ID
. Затем просто используйте Except
и передайте компаратор:
var result = big.Except(small, new ProductComparer()).ToList();
Используя простой предикат, вы можете легко достичь этого:
big.Where(p => !small.Any(o => o.id == p.id)).ToList();
который преобразуется в: select from big
где элемент (p
) не достаточен для случая, когда элемент o
в small
имеет тот же ID
.
Вы должны сказать Except
того, как сравнивать экземпляры Product
.
public class ProductEqualityComparer : IEqualityComparer<Product>
{
public bool Equals(Product x, Product y)
{
//they're both the same instance or they're both null
if(ReferanceEquals(x, y))
return true;
//only one of them is null
if(x == null || y == null)
return false;
return x.Id == y.Id;
}
public int GetHashCode(Product prod)
{
return prod == null? 0 : prod.Id.GetHashCode();
}
}
big.Except(small, new ProductEqualityComparer())
Product
:(IEqualityComparer<Product>