Jak sprawdzić, czy coś jest (nie) na liście w Pythonie?
Najtańszym i najbardziej czytelnym rozwiązaniem jest użycie in
operatora (lub w konkretnym przypadku not in
). Jak wspomniano w dokumentacji,
Operatorzy in
i not in
test na członkostwo. x in s
ocenia,
True
czy x
jest członkiem s
i w False
inny sposób. x not in s
zwraca negację x in s
.
Dodatkowo,
Operator not in
ma zdefiniowaną odwrotną wartość rzeczywistą wynoszącą in
.
y not in x
jest logicznie taki sam jak not y in x
.
Oto kilka przykładów:
'a' in [1, 2, 3]
# False
'c' in ['a', 'b', 'c']
# True
'a' not in [1, 2, 3]
# True
'c' not in ['a', 'b', 'c']
# False
Działa to również z krotkami, ponieważ krotki są haszowalne (w wyniku tego, że są również niezmienne):
(1, 2) in [(3, 4), (1, 2)]
# True
Jeśli obiekt w RHS definiuje __contains__()
metodę, in
wywoła ją wewnętrznie, jak zauważono w ostatnim akapicie rozdziału Porównania dokumentów.
... in
i not in
są obsługiwane przez typy, które są iterowalne lub implementują
__contains__()
metodę. Na przykład możesz (ale nie powinieneś) to zrobić:
[3, 2, 1].__contains__(1)
# True
in
zwiera, więc jeśli twój element znajduje się na początku listy, in
ocenia szybciej:
lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst # Expected to take longer time.
68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Jeśli chcesz zrobić coś więcej niż tylko sprawdzić, czy element znajduje się na liście, istnieją opcje:
list.index
można użyć do pobrania indeksu elementu. Jeśli ten element nie istnieje, powstaje a ValueError
.
list.count
można użyć, jeśli chcesz policzyć zdarzenia.
Problem XY: Czy rozważałeś set
s?
Zadaj sobie następujące pytania:
- czy musisz sprawdzić, czy element jest na liście więcej niż jeden raz?
- Czy to sprawdzenie jest wykonywane wewnątrz pętli lub funkcji wywoływanej wielokrotnie?
- Czy elementy, które przechowujesz na liście, można przechować? IOW, możesz do
hash
nich zadzwonić ?
Jeśli odpowiedziałeś „tak” na te pytania, powinieneś użyć set
zamiast tego. in
Test członków o list
s O (n) Złożoność. Oznacza to, że python musi wykonać liniowy skan listy, odwiedzając każdy element i porównując go z wyszukiwanym elementem. Jeśli robisz to wielokrotnie lub jeśli listy są duże, ta operacja spowoduje narzut.
set
obiekty, z drugiej strony, mieszają swoje wartości dla stałej kontroli członkostwa w czasie. Sprawdzanie odbywa się również przy użyciu in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Jeśli na tyle nieszczęście, że element, którego szukasz / nie szukasz, znajduje się na końcu listy, python przeskanuje listę do końca. Jest to widoczne z poniższych czasów:
l = list(range(100001))
s = set(l)
%timeit 100000 in l
%timeit 100000 in s
2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Przypominamy, że jest to odpowiednia opcja, o ile elementy, które przechowujesz i przeglądasz, są haszowalne. IOW musiałyby to być niezmienne typy lub obiekty, które implementują __hash__
.
3 -1 > 0 and (4-1 , 5) not in []
⤇True
dlatego błąd nie jest priorytetem operatora.