Comment vérifier si quelque chose est (ou non) dans une liste en Python ?
La solution la plus économique et la plus lisible est d'utiliser la fonction in
(ou dans votre cas spécifique, not in
). Comme indiqué dans la documentation,
Les opérateurs in
y not in
le test d'adhésion. x in s
évalue à True
si x
est un membre de s
y False
autrement. x not in s
renvoie à la négation de x in s
.
En outre,
L'opérateur not in
est défini comme ayant la valeur vraie inverse de in
.
y not in x
est logiquement la même chose que not y in x
.
Voici quelques exemples :
'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
Cela fonctionne également avec les tuples, puisque ceux-ci sont hachables (en conséquence du fait qu'ils sont également immuables) :
(1, 2) in [(3, 4), (1, 2)]
# True
Si l'objet en RHS définit un __contains__()
méthode, in
sera appelé en interne, comme indiqué dans le dernier paragraphe de la Comparaisons section de la documentation.
... in
y not in
, sont supportés par des types qui sont itérables ou qui implémentent la fonction __contains__()
méthode. Par exemple, vous pourriez (mais ne devriez pas) faire ceci :
[3, 2, 1].__contains__(1)
# True
in
court-circuite, donc si votre élément est au début de la liste, in
évalue plus rapidement :
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)
Si vous voulez faire plus que simplement vérifier si un élément se trouve dans une liste, il existe des options :
-
list.index
peut être utilisé pour récupérer l'index d'un élément. Si cet élément n'existe pas, un ValueError
est soulevée.
-
list.count
peut être utilisé si vous voulez compter les occurrences.
Le problème XY : Avez-vous envisagé set
s ?
Posez-vous ces questions :
- avez-vous besoin de vérifier si un élément se trouve dans une liste plus d'une fois ?
- Cette vérification est-elle effectuée à l'intérieur d'une boucle, ou d'une fonction appelée de manière répétée ?
- Les éléments que vous stockez dans votre liste sont-ils hachables ? C'est-à-dire que vous pouvez appeler
hash
sur eux ?
Si vous avez répondu "oui" à ces questions, vous devez utiliser un système de gestion de l'eau. set
à la place. Un site in
test d'adhésion sur list
s est d'une complexité temporelle O(n). Cela signifie que python doit effectuer un balayage linéaire de votre liste, en visitant chaque élément et en le comparant à l'élément recherché. Si vous effectuez cette opération de manière répétée, ou si les listes sont volumineuses, cette opération entraînera une surcharge.
set
d'autre part, hachent leurs valeurs pour un contrôle d'appartenance en temps constant. La vérification est également effectuée en utilisant in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Si vous avez la malchance que l'élément que vous recherchez/ne recherchez pas se trouve à la fin de votre liste, python aura scanné la liste jusqu'à la fin. C'est ce que montrent les temps ci-dessous :
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)
Pour rappel, cette option convient tant que les éléments que vous stockez et recherchez sont hachables. Autrement dit, il faudrait que ce soit des types immuables, ou des objets qui implémentent __hash__
.