443 votos

Comprobar si algo está (o no) en una lista en Python

Tengo una lista de tuplas en Python y tengo una condicional donde quiero tomar la rama SOLO si la tupla no está en la lista (si está en la lista, entonces no quiero tomar la rama if)

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

    # Do Something

Sin embargo, a mí no me funciona. ¿Qué he hecho mal?

704voto

nightcracker Puntos 34498

Probablemente el fallo esté en otra parte de tu código, porque debería funcionar bien:

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

O con tuplas:

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

51voto

coldspeed Puntos 102181

¿Cómo compruebo si algo está (o no) en una lista en Python?

La solución más barata y legible es utilizar la función in (o en su caso específico, not in ). Como se menciona en la documentación,

Los operadores in y not in prueba de adhesión. x in s e True si x es miembro de s y False de lo contrario. x not in s r la negación de x in s .

Además,

El operador not in se define para tener el valor verdadero inverso de in .

y not in x es lógicamente lo mismo que not y in x .

He aquí algunos ejemplos:

'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

Esto también funciona con tuplas, ya que las tuplas son hashables (como consecuencia del hecho de que también son inmutables):

(1, 2) in [(3, 4), (1, 2)]
#  True

Si el objeto del lado derecho define un __contains__() método, in lo llamará internamente, como se indica en el último párrafo del Comparaciones de los documentos.

... in y not in , son compatibles con el tipo __contains__() método. Por ejemplo, podrías (pero no deberías) hacer esto:

[3, 2, 1].__contains__(1)
# True

in cortocircuita, así que si tu elemento está al principio de la lista, in evalúa más rápido:

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 quieres hacer algo más que comprobar si un elemento está en una lista, hay opciones:

  • list.index se puede utilizar para recuperar el índice de un elemento. Si ese elemento no existe, aparecerá un ValueError se levanta.
  • list.count se puede utilizar si desea contar las ocurrencias.

El problema XY: ¿Ha pensado en set s?

Hágase estas preguntas:

  • ¿necesitas comprobar si un elemento está en una lista más de una vez?
  • ¿Esta comprobación se realiza dentro de un bucle, o de una función llamada repetidamente?
  • ¿Los elementos que almacenas en tu lista son hashables? Es decir, ¿puede llamar a hash en ellos?

Si ha respondido "sí" a estas preguntas, debería utilizar un set en su lugar. Un in prueba de adhesión el list s tiene una complejidad de tiempo O(n). Esto significa que Python tiene que hacer un barrido lineal de tu lista, visitando cada elemento y comparándolo con el elemento buscado. Si haces esto repetidamente, o si las listas son grandes, esta operación incurrirá en una sobrecarga.

set por otro lado, hacen hash de sus valores para comprobar la pertenencia en tiempo constante. La comprobación también se realiza mediante in :

1 in {1, 2, 3} 
# True

'a' not in {'a', 'b', 'c'}
# False

(1, 2) in {('a', 'c'), (1, 2)}
# True

Si tienes la mala suerte de que el elemento que buscas/no buscas está al final de la lista, Python habrá escaneado la lista hasta el final. Esto es evidente a partir de los tiempos de abajo:

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)

Como recordatorio, esta es una opción adecuada siempre y cuando los elementos que estés almacenando y consultando sean hashables. Es decir, tendrían que ser tipos inmutables u objetos que implementen __hash__ .

0voto

bitbuoy Puntos 83

También se puede utilizar el cuente de la clase lista: digamos que tenemos una lista:

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

Para confirmar si tenemos un elemento (es decir, 10) en la lista o No y la frecuencia de su aparición:

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

0voto

not a robot Puntos 1353

Sé que esta es una pregunta muy antigua, pero en la pregunta real del OP de "¿Qué he hecho mal?", el problema parece estar en cómo codificar:

tomar la bifurcación SÓLO si la tupla no está en la lista

Esto es lógicamente equivalente a (como OP observa)

IF tuple in list THEN don't take the branch

Sin embargo, no dice nada sobre lo que debería ocurrir IF tuple not in list . En particular no seguir que

IF tuple not in list THEN take the branch

Así que la regla de OP nunca menciona qué hacer IF tuple not in list . Aparte de eso, como las otras respuestas han señalado, not in es la sintaxis correcta para comprobar si un objeto está en una lista (o en cualquier contenedor en realidad).

my_tuple not in my_list # etc.

-1voto

Caio Marchi Puntos 3

Le site no viene justo después del operador y . Prueba esto:

si (curr_x -1 > 0 y no (curr_x-1, curr_y) en lista) :

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X