Каков самый быстрый способ определить, содержит ли один IEnumerable все элементы другого IEnumerable при сравнении поля / свойства каждого элемента в обеих коллекциях?
public class Item
{
public string Value;
public Item(string value)
{
Value = value;
}
}
//example usage
Item[] List1 = {new Item("1"),new Item("a")};
Item[] List2 = {new Item("a"),new Item("b"),new Item("c"),new Item("1")};
bool Contains(IEnumerable<Item> list1, IEnumerable<Item>, list2)
{
var list1Values = list1.Select(item => item.Value);
var list2Values = list2.Select(item => item.Value);
return //are ALL of list1Values in list2Values?
}
Contains(List1,List2) // should return true
Contains(List2,List1) // should return false
c#
.net
linq
ienumerable
Брэндон Захари
источник
источник
Ответы:
Не существует "быстрого способа" сделать это, если вы не отслеживаете и не поддерживаете какое-то состояние, определяющее, все ли значения в одной коллекции содержатся в другой. Если вам нужно
IEnumerable<T>
работать только против, я бы использовалIntersect
.Производительность этого должна быть очень разумной, поскольку
Intersect()
будет выполнять перечисление по каждому списку только один раз. Кроме того, второй вызовCount()
будет оптимальным, если базовый тип - это,ICollection<T>
а не простоIEnumerable<T>
.источник
Вы также можете использовать Except, чтобы удалить из первого списка все значения, которые существуют во втором списке, а затем проверить, все ли значения были удалены:
Преимущество этого метода состоит в том, что он не требует двух вызовов Count ().
источник
C # 3.5+
Использование,
Enumerable.All<TSource>
чтобы определить, все ли элементы List2 содержатся в List1:Это также будет работать, когда список1 содержит даже больше, чем все элементы списка2.
источник
Contains()
вызова на производительность приAll()
вызове.bool hasAll = list2Uris.All(list1Uris.Contains);
Ответ Кента хорош и краток, но решение, которое он предлагает, всегда требует итерации по всей первой коллекции. Вот исходный код:
Это не всегда требуется. Итак, вот мое решение:
Собственно, вам стоит подумать об использовании
ISet<T>
(HashSet<T>
). Он содержит все необходимые методы набора.IsSubsetOf
в твоем случае.источник
оператор Linq SequenceEqual также будет работать (но чувствителен к перечисляемым элементам, находящимся в том же порядке)
источник
Решение, отмеченное как ответ, не сработает в случае повторения. Если ваш IEnumerable содержит только отдельные значения, он пройдет.
Приведенный ниже ответ предназначен для двух списков с повторениями:
источник
Вы должны использовать HashSet вместо Array.
Пример:
Ссылка
Единственное ограничение HasSet заключается в том, что мы не можем получить элемент по индексу, например List, или получить элемент по ключу, например Dictionaries. Все, что вы можете сделать, это перечислить их (для каждого, пока и т. Д.)
Пожалуйста, дайте мне знать, работает ли это для вас
источник
вы можете использовать этот метод для сравнения двух списков
источник