2009-04-11 16 views
144

Estoy tratando de encontrar una forma breve de ver si alguno de los siguientes elementos está en una lista, pero mi primer intento no funciona. Además de escribir una función para lograr esto, es la forma más sencilla de verificar si uno de los múltiples elementos está en una lista.¿Cómo verificar si uno de los siguientes elementos está en una lista?

>>> a = [2,3,4] 
>>> print (1 or 2) in a 
False 
>>> print (2 or 1) in a 
True 
+0

Cosa graciosa, comprobé cómo se comportan 'y'. 'a = [1, 2] b = [3, 5, 2, 6, 8, 9] c = [3, 5, 6, 8, 1, 9] imprimir ( (1 y 2) en b , (2 y 1) en b , (1 y 2) en c , (2 y 1) en c, sep = '\ n') 'es Verdadero False False Verdadero –

+0

[Puede consultar aquí, puede ayudarlo] (http://stackoverflow.com/questions/3389574/check-if-multiple-strings-exist-in-another-string/40880830#40880830) –

Respuesta

165
>>> L1 = [2,3,4] 
>>> L2 = [1,2] 
>>> [i for i in L1 if i in L2] 
[2] 


>>> S1 = set(L1) 
>>> S2 = set(L2) 
>>> S1.intersection(S2) 
set([2]) 

Tanto las listas vacías como los conjuntos vacíos son False, por lo que puede usar el valor directamente como un valor de verdad.

+3

La intersección idea me dio esta idea. return len (set (a) .intersection (set (b))) – Deon

+8

FWIW - Hice una comparación de velocidad, y la primera solución ofrecida aquí fue ayunar con diferencia. – jackiekazil

+0

La respuesta de @user89788 usando un generador es mucho más rápida de nuevo, porque 'any' puede regresar temprano tan pronto como encuentre un valor' True' - no tiene que compilar toda la lista primero – Anentropic

16

¡Piensa en lo que dice el código en realidad!

>>> (1 or 2) 
1 
>>> (2 or 1) 
2 

Eso probablemente debería explicarlo. :) Python aparentemente implementa "perezoso o", lo que no debería ser una sorpresa. Se lleva a cabo algo así como esto:

def or(x, y): 
    if x: return x 
    if y: return y 
    return False 

En el primer ejemplo, y x == 1y == 2. En el segundo ejemplo, es viceversa. Es por eso que devuelve diferentes valores según el orden de ellos.

4

mejor que pude llegar a:

any([True for e in (1, 2) if e in a]) 
1

Esto lo hará en una sola línea.

>>> a=[2,3,4] 
>>> b=[1,2] 
>>> bool(sum(map(lambda x: x in b, a))) 
True 
+0

ahora no recibo un cierto aquí >>> imprimir una [2, 3, 4] >>> print b [2, 7] >>> reducir (lambda x, y: x de b , a) Falso – Deon

+0

Sí. Tienes razón. reduce() no manejaba exactamente los valores booleanos de la manera que yo pensaba. La versión revisada que escribí arriba funciona para ese caso. –

4

En algunos casos (por ejemplo, elementos de lista únicos), se pueden utilizar operaciones de conjunto.

>>> a=[2,3,4] 
>>> set(a) - set([2,3]) != set(a) 
True 
>>> 

O, usando set.isdisjoint(),

>>> not set(a).isdisjoint(set([2,3])) 
True 
>>> not set(a).isdisjoint(set([5,6])) 
False 
>>> 
19

Tal vez un poco más flojo:

a = [1,2,3,4] 
b = [2,7] 

print any((True for x in a if x in b)) 
+0

Es casi el mismo que el que publiqué. –

+4

@ BastienLéonard ... excepto que es mucho más rápido porque usa un generador y por lo tanto 'cualquier' puede regresar temprano, mientras que su versión tiene que construir toda la lista desde la comprensión antes de que 'cualquiera' pueda usarla. @ user89788 la respuesta es un poco mejor porque el doble paréntesis es innecesario – Anentropic

+0

IMO, esta debería ser la mejor respuesta –

143

Ah, Tobias me adelantó. Estaba pensando de esta ligera variación en su solución:

>>> a = [1,2,3,4] 
>>> b = [2,7] 
>>> print(any(x in a for x in b)) 
True 
+4

Me doy cuenta de que esta es una respuesta muy antigua, pero si una lista es muy larga y la otra es corta, ¿hay un orden que lo haría? rendimiento más rápido? (es decir, 'x en long para x en corto' vs' x en resumen para x en long') –

+8

@LukeSapan: Tiene razón. Ese orden se puede obtener a través de "imprimir cualquiera (x en max (a, b, key = len) para x en min (a, b, key = len))". Esto usa x en long para x en corto. – Nuclearman

+0

Esta es la mejor respuesta porque usa un generador y volverá tan pronto como se encuentre una coincidencia (como han dicho otros, ¡simplemente no en esta respuesta!). – dotcomly

0
print (1 in a) or (2 in a) 

print (2 in a) or (5 in a) 

Esta es una pregunta muy antigua, pero no estaba contento con cualquiera de las respuestas, por lo que he tenido que añadir esto para la posteridad.

4

Cuando piense "verifique si a hay en b", piense en hashes (en este caso, conjuntos). La manera más rápida es revisar la lista que desea verificar y luego verificar cada elemento allí.

Esta es la razón por la que la respuesta de Joe Koberg es rápida: la comprobación de la intersección establecida es muy rápida.

Sin embargo, cuando no tienes muchos datos, hacer conjuntos puede ser una pérdida de tiempo. Por lo tanto, se puede hacer un conjunto de la lista y sólo comprobar cada elemento:

tocheck = [1,2] # items to check 
a = [2,3,4] # the list 

a = set(a) # convert to set (O(len(a))) 
print [i for i in tocheck if i in a] # check items (O(len(tocheck))) 

Cuando el número de elementos que desea comprobar es pequeño, la diferencia puede ser insignificante. Pero compruebe muchos números contra una lista grande ...

pruebas:

from timeit import timeit 

methods = ['''tocheck = [1,2] # items to check 
a = [2,3,4] # the list 
a = set(a) # convert to set (O(n)) 
[i for i in tocheck if i in a] # check items (O(m))''', 

'''L1 = [2,3,4] 
L2 = [1,2] 
[i for i in L1 if i in L2]''', 

'''S1 = set([2,3,4]) 
S2 = set([1,2]) 
S1.intersection(S2)''', 

'''a = [1,2] 
b = [2,3,4] 
any(x in a for x in b)'''] 

for method in methods: 
    print timeit(method, number=10000) 

print 

methods = ['''tocheck = range(200,300) # items to check 
a = range(2, 10000) # the list 
a = set(a) # convert to set (O(n)) 
[i for i in tocheck if i in a] # check items (O(m))''', 

'''L1 = range(2, 10000) 
L2 = range(200,300) 
[i for i in L1 if i in L2]''', 

'''S1 = set(range(2, 10000)) 
S2 = set(range(200,300)) 
S1.intersection(S2)''', 

'''a = range(200,300) 
b = range(2, 10000) 
any(x in a for x in b)'''] 

for method in methods: 
    print timeit(method, number=1000) 

velocidades:

M1: 0.0170331001282 # make one set 
M2: 0.0164539813995 # list comprehension 
M3: 0.0286040306091 # set intersection 
M4: 0.0305438041687 # any 

M1: 0.49850320816 # make one set 
M2: 25.2735087872 # list comprehension 
M3: 0.466138124466 # set intersection 
M4: 0.668627977371 # any 

El método que es rápido y consistente es hacer un juego (de la lista), pero la intersección trabaja en grandes conjuntos de datos el mejor!

11
a = {2,3,4} 
if {1,2} & a: 
    pass 

Código versión de golf. Considere usar un conjunto si tiene sentido hacerlo. Encuentro esto más legible que una lista de comprensión.

+2

Para mí, esta es de lejos la solución más fácil de leer. ¡Bonito! –

7

1 línea sin comprensión de la lista.

>>> any(map(lambda each: each in [2,3,4], [1,2])) 
True 
>>> any(map(lambda each: each in [2,3,4], [1,5])) 
False 
>>> any(map(lambda each: each in [2,3,4], [2,4])) 
True 
-3

Simple.

_new_list = [] 
for item in a: 
    if item in b: 
     _new_list.append(item) 
    else: 
     pass 
+1

Esto no responde la pregunta. OP quiere saber si * cualquier valor de la lista * 'a' está en la lista' b'. – That1Guy

Cuestiones relacionadas