424 votes

Vérifier si quelque chose est (pas) dans une liste en Python

J'ai une liste de tuples dans Python et j'ai une conditionnelle où je veux prendre la branche SEULEMENT si le tuple n'est pas dans la liste (s'il est dans la liste, alors je ne veux pas prendre la branche if).

if curr_x -1 > 0 and (curr_x-1 , curr_y) not in myList: 

    # Do Something

Mais cela ne fonctionne pas vraiment pour moi. Qu'est-ce que j'ai fait de mal ?

668voto

nightcracker Points 34498

Le bogue se trouve probablement ailleurs dans votre code, car il devrait fonctionner correctement :

>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True

Ou avec des tuples :

>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True

44voto

coldspeed Points 111053

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__ .

0voto

bitbuoy Points 83

On peut également utiliser le compter de la classe liste : disons que nous avons une liste :

x = [10,20,30,40,50]

Pour confirmer si nous avons un élément (i.e. 10) dans la liste ou Non et la fréquence de son apparition :

if x.count(10):
    print(x.count(10)) 
else:
    print(10," Not in the list")

-1voto

Caio Marchi Points 3

Le site pas vient juste après l'opérateur y . Essayez ceci :

si (curr_x -1 > 0 et pas (curr_x-1, curr_y) dans la liste) :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X