Muszę sprawdzić, czy lista jest podzbiorem innego - szukam zwrotu boolowskiego.
Czy testowanie równości na mniejszej liście po skrzyżowaniu jest najszybszym sposobem na to? Wydajność ma ogromne znaczenie, biorąc pod uwagę liczbę zestawów danych, które należy porównać.
Dodanie dalszych faktów na podstawie dyskusji:
Czy któraś z list będzie taka sama dla wielu testów? Robi to, ponieważ jednym z nich jest statyczna tabela odnośników.
Czy to musi być lista? Tak nie jest - statyczna tabela odnośników może być czymkolwiek, co działa najlepiej. Dynamiczny to dykt, z którego wyodrębniamy klucze w celu przeprowadzenia wyszukiwania statycznego.
Jakie byłoby optymalne rozwiązanie biorąc pod uwagę scenariusz?
Odpowiedzi:
Funkcja wykonawcza, którą zapewnia Python, to
set.issubset
. Ma jednak kilka ograniczeń, które sprawiają, że nie jest jasne, czy jest to odpowiedź na twoje pytanie.Lista może zawierać elementy wiele razy i ma określoną kolejność. Zestaw nie. Dodatkowo zestawy działają tylko na obiektach mieszających się .
Czy pytasz o podzbiór lub podsekwencję (co oznacza, że będziesz potrzebować algorytmu wyszukiwania ciągu)? Czy któraś z list będzie taka sama dla wielu testów? Jakie typy danych są zawarte na liście? A jeśli chodzi o to, czy musi to być lista?
Twój drugi post przecina dykt, a lista wyjaśniła typy i otrzymała zalecenie użycia widoków klucza słownika dla ich funkcji podobnej do zestawu. W takim przypadku wiadomo, że działa, ponieważ klucze słownika zachowują się jak zestaw (do tego stopnia, że zanim mieliśmy zestawy w Pythonie korzystaliśmy ze słowników). Można się zastanawiać, jak problem stał się mniej szczegółowy w ciągu trzech godzin.
źródło
źródło
set(a).issubset(b)
ponieważ w tym przypadku konwertujesz tylkoa
na zestaw, ale nieb
, co oszczędza czas. Możesz użyćtimeit
do porównania czasu zajętego przez dwa polecenia. Na przykładtimeit.repeat('set(a)<set(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
itimeit.repeat('set(a).issubset(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
issubset
jest sprawdzenie, czy argumentem jestset
/frozenset
, a jeśli nie, konwertuje go na tymczasowyset
dla porównania, uruchamia czek, a następnie wyrzuca tymczasowyset
. Różnice czasowe (jeśli występują) byłyby czynnikiem niewielkich różnic w kosztach wyszukiwania LEGB (znalezienieset
drugiego czasu jest droższe niż wyszukiwanie atrybutów w przypadku istniejącegoset
), ale przeważnie jest to pranie dla wystarczająco dużych danych wejściowych.Objaśnienie: Generator tworzy wartości logiczne, przeglądając listę,
one
sprawdzając, czy ten element znajduje się na liścietwo
.all()
zwraca,True
jeśli każdy element jest prawdziwy, w przeciwnym razieFalse
.Zaletą jest również to, że
all
zwraca False przy pierwszym wystąpieniu brakującego elementu, zamiast konieczności przetwarzania każdego elementu.źródło
set(one).issubset(set(two))
jest to świetne rozwiązanie. Dzięki rozwiązaniu, które opublikowałem, powinieneś być w stanie używać go z dowolnymi obiektami, jeśli mają one zdefiniowane odpowiednie operatory porównania.all
na prawidłowe zwarcie, drugie przeprowadzi wszystkie kontrole, nawet jeśli z pierwszej kontroli będzie jasne, że test się nie powiedzie. Po prostu upuść nawiasy kwadratowe, aby uzyskaćall(x in two for x in one)
.Zakładając, że przedmioty są haszowalne
Jeśli nie obchodzą Cię duplikaty przedmiotów, np.
[1, 2, 2]
a[1, 2]
następnie użyj:.issubset
będzie najszybszym sposobem na zrobienie tego. Sprawdzanie długości przed testowaniemissubset
nie poprawi prędkości, ponieważ nadal masz O (N + M) elementów do iteracji i sprawdzania.źródło
Jeszcze jednym rozwiązaniem byłoby użycie
intersection
.Przecięcie zbiorów zawierałoby
set one
(LUB)
źródło
Jeśli lista 1 znajduje się na liście 2:
(x in two for x in one)
generuje listęTrue
.kiedy robimy,
set(x in two for x in one)
ma tylko jeden element (prawda).źródło
Teoria zestawów jest nieodpowiednia dla list, ponieważ duplikaty skutkują błędnymi odpowiedziami przy użyciu teorii zbiorów.
Na przykład:
Nie ma znaczenia. Tak, daje fałszywą odpowiedź, ale nie jest to poprawne, ponieważ teoria mnogości po prostu porównuje: 1,3,5 wobec 1,3,4,5. Musisz dołączyć wszystkie duplikaty.
Zamiast tego musisz policzyć każde wystąpienie każdego elementu i wykonać sprawdzenie większe niż równe. Nie jest to bardzo drogie, ponieważ nie wykorzystuje operacji O (N ^ 2) i nie wymaga szybkiego sortowania.
Następnie uruchamiając to otrzymujesz:
źródło
Ponieważ nikt nie rozważał porównania dwóch ciągów, oto moja propozycja.
Możesz oczywiście chcieć sprawdzić, czy potok („|”) nie jest częścią żadnej listy i może automatycznie wybrał inny znak, ale masz pomysł.
Użycie pustego ciągu jako separatora nie jest rozwiązaniem, ponieważ liczby mogą mieć kilka cyfr ([12,3]! = [1,23])
źródło
Wybacz mi, jeśli spóźnię się na przyjęcie. ;)
Aby sprawdzić, czy jeden
set A
jest podzbioremset B
,Python
maA.issubset(B)
iA <= B
. Działaset
tylko i działa świetnie, ALE złożoność implementacji wewnętrznej jest nieznana. Odniesienie: https://docs.python.org/2/library/sets.html#set-objectsWymyśliłem algorytm, aby sprawdzić, czy
list A
jest podzbioremlist B
następujących uwag.sort
najpierw porównać obie listy przed porównaniem elementów w celu zakwalifikowania do podzbioru.break
loop
B[j]
A[i]
last_index_j
służy do rozpoczynanialoop
odlist B
miejsca, w którym zostało ostatnio przerwane. Pomaga uniknąć rozpoczynania porównań od początkulist B
(co, jak można się domyślać, jest niepotrzebne, zaczynalist B
odindex 0
następnegoiterations
).Złożoność będzie polegać
O(n ln n)
na sortowaniu obu list iO(n)
sprawdzaniu podzbioru.O(n ln n) + O(n ln n) + O(n) = O(n ln n)
.Kod zawiera wiele
print
instrukcji, aby zobaczyć, co się dzieje w każdymiteration
z nichloop
. Są one przeznaczone wyłącznie do zrozumienia.Sprawdź, czy jedna lista jest podzbiorem innej listy
Wynik
źródło
Poniższy kod sprawdza, czy dany zestaw jest „właściwym podzbiorem” innego zestawu
źródło
W Pythonie 3.5 możesz zrobić a,
[*set()][index]
aby uzyskać element. Jest to znacznie wolniejsze rozwiązanie niż inne metody.lub po prostu z Len i Set
źródło
Oto skąd wiem, że jeśli jedna lista jest podzbiorem innej, sekwencja ma dla mnie znaczenie.
źródło
Większość rozwiązań uważa, że listy nie mają duplikatów. Jeśli Twoje listy zawierają duplikaty, możesz spróbować:
Zapewnia, że lista podrzędna nigdy nie zawiera innych elementów niż lista lub większa część wspólnego elementu.
źródło
Jeśli pytasz, czy jedna lista jest „zawarta” na innej liście, to:
Jeśli pytasz, czy każdy element na liście A ma taką samą liczbę pasujących elementów na liście B, spróbuj:
źródło
Jeśli
a2 is subset of a1
takLength of set(a1 + a2) == Length of set(a1)
źródło