python - lenguaje - ¿Cómo verificar si uno de los siguientes elementos está en una lista?
python tutorial (13)
¡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. Lo realiza algo como esto:
def or(x, y):
if x: return x
if y: return y
return False
En el primer ejemplo, x == 1
e y == 2
. En el segundo ejemplo, es viceversa. Es por eso que devuelve diferentes valores según el orden de ellos.
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.
>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True
1 línea sin listas de comprensión.
>>> 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
Ah, Tobías me lo ganaste. Estaba pensando en 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
Cuando piense "verificar si hay a 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 cual la respuesta de Joe Koberg es rápida: verificar la intersección establecida es muy rápido.
Sin embargo, cuando no tienes muchos datos, hacer conjuntos puede ser una pérdida de tiempo. Entonces, puedes hacer un conjunto de la lista y simplemente verificar cada ítem:
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 la cantidad de elementos que desea verificar es pequeña, 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 consistentemente rápido es hacer un conjunto (de la lista), ¡pero la intersección funciona mejor en grandes conjuntos de datos!
En algunos casos (por ejemplo, elementos de lista únicos), se pueden usar operaciones de conjunto.
>>> a=[2,3,4]
>>> set(a) - set([2,3]) != set(a)
True
>>>
O bien, utilizando set.isdisjoint() ,
>>> not set(a).isdisjoint(set([2,3]))
True
>>> not set(a).isdisjoint(set([5,6]))
False
>>>
Esto lo hará en una línea.
>>> a=[2,3,4]
>>> b=[1,2]
>>> bool(sum(map(lambda x: x in b, a)))
True
Lo mejor que se me ocurrió fue:
any([True for e in (1, 2) if e in a])
Recopilé varias de las soluciones mencionadas en otras respuestas y en comentarios, luego realicé una prueba de velocidad. not set(a).isdisjoint(b)
resultó ser el más rápido, tampoco disminuyó mucho cuando el resultado fue False
.
Cada una de las tres pruebas prueba una pequeña muestra de las posibles configuraciones de b
. Los tiempos son en microsegundos.
Any with generator and max
2.093 1.997 7.879
Any with generator
0.907 0.692 2.337
Any with list
1.294 1.452 2.137
True in list
1.219 1.348 2.148
Set with &
1.364 1.749 1.412
Set intersection explcit set(b)
1.424 1.787 1.517
Set intersection implicit set(b)
0.964 1.298 0.976
Set isdisjoint explicit set(b)
1.062 1.094 1.241
Set isdisjoint implicit set(b)
0.622 0.621 0.753
import timeit
def printtimes(t):
print ''{:.3f}''.format(t/10.0),
setup1 = ''a = range(10); b = range(9,15)''
setup2 = ''a = range(10); b = range(10)''
setup3 = ''a = range(10); b = range(10,20)''
print ''Any with generator and max/n/t'',
printtimes(timeit.Timer(''any(x in max(a,b,key=len) for x in min(b,a,key=len))'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''any(x in max(a,b,key=len) for x in min(b,a,key=len))'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''any(x in max(a,b,key=len) for x in min(b,a,key=len))'',setup=setup3).timeit(10000000))
print
print ''Any with generator/n/t'',
printtimes(timeit.Timer(''any(i in a for i in b)'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''any(i in a for i in b)'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''any(i in a for i in b)'',setup=setup3).timeit(10000000))
print
print ''Any with list/n/t'',
printtimes(timeit.Timer(''any([i in a for i in b])'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''any([i in a for i in b])'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''any([i in a for i in b])'',setup=setup3).timeit(10000000))
print
print ''True in list/n/t'',
printtimes(timeit.Timer(''True in [i in a for i in b]'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''True in [i in a for i in b]'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''True in [i in a for i in b]'',setup=setup3).timeit(10000000))
print
print ''Set with &/n/t'',
printtimes(timeit.Timer(''bool(set(a) & set(b))'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''bool(set(a) & set(b))'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''bool(set(a) & set(b))'',setup=setup3).timeit(10000000))
print
print ''Set intersection explcit set(b)/n/t'',
printtimes(timeit.Timer(''bool(set(a).intersection(set(b)))'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''bool(set(a).intersection(set(b)))'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''bool(set(a).intersection(set(b)))'',setup=setup3).timeit(10000000))
print
print ''Set intersection implicit set(b)/n/t'',
printtimes(timeit.Timer(''bool(set(a).intersection(b))'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''bool(set(a).intersection(b))'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''bool(set(a).intersection(b))'',setup=setup3).timeit(10000000))
print
print ''Set isdisjoint explicit set(b)/n/t'',
printtimes(timeit.Timer(''not set(a).isdisjoint(set(b))'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''not set(a).isdisjoint(set(b))'',setup=setup2).timeit(10000000))
printtimes(timeit.Timer(''not set(a).isdisjoint(set(b))'',setup=setup3).timeit(10000000))
print
print ''Set isdisjoint implicit set(b)/n/t'',
printtimes(timeit.Timer(''not set(a).isdisjoint(b)'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''not set(a).isdisjoint(b)'',setup=setup1).timeit(10000000))
printtimes(timeit.Timer(''not set(a).isdisjoint(b)'',setup=setup3).timeit(10000000))
print
Sencillo.
_new_list = []
for item in a:
if item in b:
_new_list.append(item)
else:
pass
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))
>>> 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 falsos, por lo que puede usar el valor directamente como un valor de verdad.
a = {2,3,4}
if {1,2} & a:
pass
Código de golf versión. Considere usar un conjunto si tiene sentido hacerlo. Encuentro esto más legible que una lista de comprensión.
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 ninguna de las respuestas, así que tuve que agregar esto por el bien de la posteridad.