2011-01-30 12 views
329

Tengo una lista:Comprobar si un elemento de la lista de Python contiene una cadena dentro de otra cadena

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456'] 

y quiero buscar elementos que contienen la cadena 'abc'. ¿Cómo puedo hacer eso?

if 'abc' in my_list: 

sería comprobar si 'abc' existe en la lista, pero es una parte de 'abc-123' y 'abc-456', 'abc' no existe por sí mismo. Entonces, ¿cómo puedo obtener todos los artículos que contienen 'abc'?

+11

Para comprobar lo contrario (si una cadena contiene una entre varias cadenas): http://stackoverflow.com/a/6531704/2436175 – Antonio

Respuesta

555

Si sólo desea comprobar la presencia de abc en cualquier cadena en la lista, usted podría intentar

some_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456'] 
if any("abc" in s for s in some_list): 
    # whatever 

Si usted realmente desea conseguir todos los artículos que contengan abc, utilice

matching = [s for s in some_list if "abc" in s] 
+0

tengo que comprobar si un elemento está en una matriz de 6 elementos. ¿Es más rápido hacer 6 "si" o es lo mismo? –

+19

@OlivierPons, simplemente haz 'if myitem en myarray:' – alldayremix

+5

Otra forma de obtener todas las cadenas que contienen subcadena 'abc': 'filter (elemento lambda: 'abc' en element, some_list)' – hangtwenty

9
x = 'aaa' 
L = ['aaa-12', 'bbbaaa', 'cccaa'] 
res = [y for y in L if x in y] 
6
any('abc' in item for item in mylist) 
61

uso filter para llegar a los elementos que tienen abc.

>>> lst = ['abc-123', 'def-456', 'ghi-789', 'abc-456'] 
>>> print filter(lambda x: 'abc' in x, lst) 
['abc-123', 'abc-456'] 

También puede usar una lista de comprensión.

>>> [x for x in lst if 'abc' in x] 

Por cierto, no usan la palabra list como nombre de variable, puesto que ya se utiliza para el tipo list.

8
for item in my_list: 
    if item.find("abc") != -1: 
     print item 
+0

Si va a tomar este enfoque, creo que es más idiomático hacer' si 'abc' en el elemento' más bien usando 'item.find ('abc') == -1'. –

19

Esto es muy una vieja pregunta, pero me ofrecen esta respuesta porque las respuestas anteriores no hacer frente a los elementos de la lista que no son cadenas (o algún tipo de objeto iterable). Dichos elementos causarían que la comprensión de la lista completa fallara con una excepción.

Para hacer frente con gracia con tales elementos de la lista por saltarse los artículos no iterables, usa la siguiente:

[el for el in lst if isinstance(el, collections.Iterable) and (st in el)] 

entonces, con una lista de este tipo:

lst = [None, 'abc-123', 'def-456', 'ghi-789', 'abc-456', 123] 
st = 'abc' 

seguirá recibiendo los elementos que coinciden (['abc-123', 'abc-456'])

la prueba para iterables pueden no ser la mejor. Lo tengo desde aquí: In Python, how do I determine if an object is iterable?

+0

¿No sería '[el for el in lst si el y (st in el)]' tener más sentido en el ejemplo dado? – tinix

+0

@tinix Yo no manejaré con gracia los objetos no iterables, ¿o sí? –

+0

"ejemplo dado" 'my_list = [ 'abc-123', 'def-456', 'ghi-789', 'abc-456']' hay necesidad de complicar más la misma. – tinix

37

sólo tirar esto hacia fuera allí: si por casualidad que coincidir contra más de una cadena, por ejemplo abc y def, puede poner combinar dos listas por comprensión de la siguiente manera:

matchers = ['abc','def'] 
matching = [s for s in my_list if any(xs in s for xs in matchers)] 

salida:

['abc-123', 'def-456', 'abc-456'] 
+1

Esto era exactamente lo que buscaba en Google ... ¡Gracias! – N8TRO

+1

También podría usar '{s para s en mi_lista para xs en emparejamientos si xs en s}' (tenga en cuenta los corchetes para crear un conjunto único). Puede ser más fácil de leer, pero podría ser más lento si la mayoría de los valores 's' tendrán una coincidencia, ya que su' any' se detendrá eficientemente en la primera coincidencia. –

0

Desde mi conocimiento, un 'por' declaración siempre consumirá tiempo.

Cuando la longitud de la lista está creciendo, el tiempo de ejecución también aumentará.

Creo que, buscar una subcadena en una cadena con la instrucción 'es' es un poco más rápido.

In [1]: t = ["abc_%s" % number for number in range(10000)] 

In [2]: %timeit any("9999" in string for string in t) 
1000 loops, best of 3: 420 µs per loop 

In [3]: %timeit "9999" in ",".join(t) 
10000 loops, best of 3: 103 µs per loop 

embargo, estoy de acuerdo que la declaración any es más fácil de leer.

14

Este es el camino más corto:

if 'abc' in str(my_list): 
+0

Esto fallaría si tuviera una lista de ["abc1", "1abc2"] ya que encontraría una coincidencia porque la cadena 'abc' estaría en la cadena recién creada – cgseller

+0

Sí, este es el comportamiento previsto ... verdadero si alguno de los elementos contiene 'abc' – RogerS

+0

, no sé por qué todas estas otras personas deciden hacer esas complicadas soluciones lambda cuando no las necesitan. Buen trabajo @RogerS – ntk4

Cuestiones relacionadas