Jaki jest najszybszy sposób określenia, czy jeden element IEnumerable zawiera wszystkie elementy innego elementu IEnumerable podczas porównywania pola / właściwości każdego elementu w obu kolekcjach?
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
Brandon Zacharie
źródło
źródło
Odpowiedzi:
Nie ma na to „szybkiego sposobu”, chyba że śledzisz i utrzymujesz pewien stan, który określa, czy wszystkie wartości w jednej kolekcji znajdują się w innej. Jeśli musisz tylko
IEnumerable<T>
przeciwdziałać, użyłbymIntersect
.Wykonanie tego powinno być bardzo rozsądne, ponieważ
Intersect()
wyliczę na każdej liście tylko raz. Ponadto drugie wywołanieCount()
będzie optymalne, jeśli typem bazowym jest,ICollection<T>
a nie tylkoIEnumerable<T>
.źródło
Możesz również użyć opcji Wyjątek, aby usunąć z pierwszej listy wszystkie wartości, które istnieją na drugiej liście, a następnie sprawdzić, czy wszystkie wartości zostały usunięte:
Ta metoda miała tę zaletę, że nie wymagała dwóch wywołań funkcji Count ().
źródło
C # 3.5+
Używanie
Enumerable.All<TSource>
do określenia, czy wszystkie elementy z listy List2 znajdują się na liście List1:Będzie to również działać, gdy lista1 zawiera nawet więcej niż wszystkie elementy z listy2.
źródło
Contains()
połączenia na wydajność podczasAll()
rozmowy.bool hasAll = list2Uris.All(list1Uris.Contains);
Odpowiedź Kenta jest dobra i krótka, ale rozwiązanie, które zapewnia, zawsze wymaga powtórzenia całej pierwszej kolekcji. Oto kod źródłowy:
Nie zawsze jest to wymagane. Oto moje rozwiązanie:
Właściwie powinieneś pomyśleć o użyciu
ISet<T>
(HashSet<T>
). Zawiera wszystkie wymagane metody zestawu.IsSubsetOf
w Twoim przypadku.źródło
Operator Linq SequenceEqual również działałby (ale jest wrażliwy na elementy wyliczalne w tej samej kolejności)
źródło
Rozwiązanie oznaczone jako odpowiedź zawiodłoby w przypadku powtórzeń. Jeśli twój IEnumerable zawiera tylko różne wartości, to zostanie przekazany.
Poniższa odpowiedź dotyczy 2 list z powtórzeniami:
źródło
Powinieneś użyć HashSet zamiast Array.
Przykład:
Odniesienie
Jedynym ograniczeniem HasSet jest to, że nie możemy uzyskać elementu według indeksu, takiego jak Lista, ani uzyskać elementu według klucza, takiego jak Dictionaries. Wszystko, co możesz zrobić, to je wyliczyć (dla każdego, podczas itd.)
Daj mi znać, jeśli to Ci odpowiada
źródło
możesz użyć tej metody do porównania dwóch list
źródło