Muszę porównać dwie listy, aby utworzyć nową listę konkretnych elementów znajdujących się na jednej liście, ale nie na drugiej. Na przykład:
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
Chcę przejrzeć listę_1 i dołączyć do main_list wszystkie elementy z listy_2, których nie ma na liście_1.
Wynik powinien być:
main_list=["f", "m"]
Jak mogę to zrobić w Pythonie?
list_2
które nigdzie nie występują w,list_1
lub elementówlist_2
, które nie występują w tym samym indeksie wlist_1
?Odpowiedzi:
TL; DR:
ROZWIĄZANIE (1)
ROZWIĄZANIE (2) Chcesz posortowaną listę
Objaśnienia:
(1) Można użyć NumPy użytkownika
setdiff1d
(array1
,array2
,assume_unique
=False
).assume_unique
pyta użytkownika, JEŻELI tablice SĄ JUŻ UNIKALNE.Jeśli
False
, to unikalne elementy są określane jako pierwsze.Jeśli
True
funkcja przyjmie, że elementy są już unikalne ORAZ funkcja pominie określanie unikalnych elementów.Daje to unikatowe wartości w
array1
które nie są warray2
.assume_unique
jestFalse
domyślnie.Jeśli obawiasz się unikalnych elementów (na podstawie odpowiedzi Chinny84 ), po prostu użyj (gdzie
assume_unique=False
=> wartość domyślna):(2) Dla tych, którzy chcą posortować odpowiedzi, stworzyłem niestandardową funkcję:
Aby uzyskać odpowiedź, uruchom:
UWAGI BOCZNE:
(a) Rozwiązanie 2 (funkcja niestandardowa
setdiff_sorted
) zwraca listę (w porównaniu z tablicą w rozwiązaniu 1).(b) Jeśli nie jesteś pewien, czy elementy są unikalne, po prostu użyj domyślnego ustawienia NumPy
setdiff1d
w obu rozwiązaniach A i B. Co może być przykładem komplikacji? Patrz uwaga (c).(c) Sytuacja będzie wyglądać inaczej, jeśli żadna z tych dwóch list nie jest unikalna.
Powiedzmy
list_2
nie jest unikalna:list2 = ["a", "f", "c", "m", "m"]
. Keeplist1
as is:list_1 = ["a", "b", "c", "d", "e"]
Ustawienie domyślnej wartości
assume_unique
uzysku["f", "m"]
(w obu rozwiązaniach). JEDNAK, jeśli ustawiszassume_unique=True
, oba rozwiązania dają["f", "m", "m"]
. Czemu? Dzieje się tak, ponieważ użytkownik ZAKŁADAŁ, że elementy są unikalne). Dlatego LEPIEJ ZACHOWAĆassume_unique
do wartości domyślnej. Zwróć uwagę, że obie odpowiedzi są posortowane.pytontępy
źródło
Możesz użyć zestawów:
Wynik:
Zgodnie z komentarzem @JonClements, oto bardziej uporządkowana wersja:
źródło
unique
elementach, ale co, jeśli mamym's
na przykład wiele, to nie podniesie tego.list(set(list_2).difference(list_1))
uniknięcie jawnejset
konwersji ...Nie jestem pewien, dlaczego powyższe wyjaśnienia są tak skomplikowane, gdy masz dostępne metody natywne:
źródło
Użyj takiego rozumienia listy :
Wynik:
Edytować:
Jak wspomniano w komentarzach poniżej, przy dużych listach powyższe nie jest idealnym rozwiązaniem. W takim przypadku lepszą opcją byłaby konwersja
list_1
naset
pierwszą:źródło
list_1
, chciałbyś wstępnie przekonwertować naset
/frozenset
, np.set_1 = frozenset(list_1)
Następniemain_list = [item for item in list_2 if item not in set_1]
skrócić czas sprawdzania zO(n)
na element do (w przybliżeniu)O(1)
.enumerate()
do tego:[index for (index, item) in enumerate(list_2) if item not in list_1]
Jeśli chcesz rozwiązanie jednej liniowej (ignorując importu), który wymaga tylko
O(max(n, m))
pracę dla wejść długościn
im
, a nieO(n * m)
pracy, można to zrobić z tymitertools
module :Wykorzystuje to funkcje funkcjonalne, które podczas konstrukcji przyjmują funkcję zwrotną, umożliwiając jednokrotne utworzenie wywołania zwrotnego i ponowne użycie go dla każdego elementu bez konieczności przechowywania go gdzieś (ponieważ
filterfalse
przechowuje go wewnętrznie); Listy składane i wyrażenia generatora mogą to zrobić, ale jest to brzydkie. †To daje takie same wyniki w jednym wierszu, jak:
z prędkością:
Oczywiście, jeśli porównania mają być pozycyjne, to:
powinien produkować:
(ponieważ wartość w
list_2
ma dopasowanie w tym samym indeksie wlist_1
), zdecydowanie powinieneś wybrać odpowiedź Patryka , która nie zawiera tymczasowychlist
s lubset
s (nawet jeśliset
s jest z grubszaO(1)
, mają wyższy współczynnik „stały” na sprawdzenie niż proste sprawdzenia równości ) i wymagaO(min(n, m))
pracy, mniej niż jakakolwiek inna odpowiedź, a jeśli twój problem jest wrażliwy na położenie, jest jedynym poprawnym rozwiązaniem, gdy pasujące elementy pojawiają się przy niedopasowanych przesunięciach.†: Sposobem na zrobienie tego samego z rozumieniem listy jako jednowierszowym byłoby nadużywanie zagnieżdżonych pętli w celu tworzenia i buforowania wartości w „najbardziej zewnętrznej” pętli, np .:
co również daje niewielką korzyść w zakresie wydajności w Pythonie 3 (ponieważ teraz
set_1
jest lokalnie objęty zakresem kodu zrozumienia, zamiast wyszukiwać w zagnieżdżonym zakresie dla każdego sprawdzenia; w Pythonie 2 to nie ma znaczenia, ponieważ Python 2 nie używa domknięć dla listy składane; działają w tym samym zakresie, w którym są używane).źródło
wynik:
źródło
list_1
jest duże ilist_2
ma niebanalny rozmiar, ponieważ obejmujelen(list_2)
O(n)
skanowanielist_1
, wykonanie goO(n * m)
(gdzien
im
są długościamilist_2
ilist_1
odpowiednio). Jeśli przekonwertujeszlist_1
naset
/ zfrozenset
góry, sprawdzanie zawartości można wykonać wO(1)
, co daje całkowitą pracęO(n)
na długościlist_2
(technicznieO(max(n, m))
, ponieważ pracujeszO(m)
nad wykonaniemset
).Chciałbym zestawić
zip
listy razem, aby porównać je element po elemencie.źródło
list
z jednymlist
konstruowanym nowym , bez dodatkowych tymczasowych , żadnych kosztownych kontroli bezpieczeństwa itp.Użyłem dwóch metod i okazało się, że jedna z nich jest bardziej użyteczna niż druga. Oto moja odpowiedź:
Moje dane wejściowe:
Metoda 1:
np.setdiff1d
Podoba mi się to podejście w porównaniu z innymi, ponieważ zachowuje pozycjęMetoda 2: Chociaż daje taką samą odpowiedź jak w metodzie 1, ale zakłóca porządek
Metoda 1
np.setdiff1d
doskonale spełnia moje wymagania. Ta odpowiedź dla informacji.źródło
Jeśli należy wziąć pod uwagę liczbę wystąpień, prawdopodobnie trzeba użyć czegoś takiego
collections.Counter
:Zgodnie z obietnicą może to również obsługiwać różną liczbę wystąpień jako „różnicę”:
źródło
Z ser1 usuń elementy obecne w ser2.
Wejście
ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])
Rozwiązanie
ser1 [~ ser1.isin (ser2)]
źródło