Cómo verificar si una cadena contiene un elemento de una lista en Python

217

Tengo algo como esto:

extensionsToCheck = ['.pdf', '.doc', '.xls']

for extension in extensionsToCheck:
    if extension in url_string:
        print(url_string)

Me pregunto cuál sería la forma más elegante de hacer esto en Python (sin usar el bucle for). Estaba pensando en algo como esto (como de C / C ++), pero no funcionó:

if ('.pdf' or '.doc' or '.xls') in url_string:
    print(url_string)

Editar: estoy un poco obligado a explicar cómo esto es diferente a la pregunta a continuación, que está marcada como duplicado potencial (por lo que no se cierra, supongo).

La diferencia es que quería verificar si una cadena es parte de alguna lista de cadenas, mientras que la otra pregunta es verificar si una cadena de una lista de cadenas es una subcadena de otra cadena. Similar, pero no exactamente lo mismo, y la semántica es importante cuando buscas una respuesta en línea en mi humilde opinión. Estas dos preguntas buscan resolver el problema opuesto el uno del otro. Sin embargo, la solución para ambos resulta ser la misma.

pootzko
fuente
44
Posible duplicado de Verificar si existen múltiples cadenas en otra cadena
GingerPlusPlus

Respuestas:

419

Use un generador junto con any, que cortocircuita en el primer Verdadero:

if any(ext in url_string for ext in extensionsToCheck):
    print(url_string)

EDITAR: veo que esta respuesta ha sido aceptada por OP. Aunque mi solución puede ser una solución "suficientemente buena" para su problema particular, y es una buena forma general de verificar si alguna cadena de una lista se encuentra en otra cadena, tenga en cuenta que esto es todo lo que hace esta solución. No le importa DONDE se encuentre la cadena, por ejemplo, al final de la cadena . Si esto es importante, como suele ser el caso con las URL, debe buscar la respuesta de @Wladimir Palant, o corre el riesgo de obtener falsos positivos.

Lauritz V. Thaulow
fuente
1
Esto era exactamente lo que estaba buscando. en mi caso no importa en qué parte de la cadena se encuentre la extensión. gracias
pootzko
Gran sugerencia Utilizando este ejemplo, así es como verifico si alguno de los argumentos coincide con los conocidos indicadores de ayuda: any ([x.lower () en ['-?', '- h', '- help', '/ h '] para x en sys.argv [1:]])
AX Labs
@ AX-Labs utilizando las comprensiones de la lista en el interior anynegará algunas de las posibles ganancias que proporciona el cortocircuito, porque toda la lista tendrá que construirse en todos los casos. Si usa la expresión sin corchetes ( any(x.lower() in ['-?','-h','--help', '/h'] for x in sys.argv[1:])), la x.lower() in [...]parte solo se evaluará hasta que se encuentre un valor Verdadero.
Lauritz V. Thaulow
55
¿Y si quiero saber qué ext es cuando any () devuelve True?
Peter Senna
@PeterSenna: any()solo devolverá verdadero o falso , pero vea la respuesta de comprensión de la lista de @psun a continuación con esta modificación:print [extension for extension in extensionsToCheck if(extension in url_string)]
Dannid
45
extensionsToCheck = ('.pdf', '.doc', '.xls')

'test.doc'.endswith(extensionsToCheck)   # returns True

'test.jpg'.endswith(extensionsToCheck)   # returns False
eumiro
fuente
55
este es inteligente, ¡no sabía que las tuplas podrían hacer eso !, pero solo funciona cuando su subcadena está anclada a un extremo de la cadena.
Dannid el
3
Muy fresco. Solo desearía que hubiera algo como "contiene" en lugar de solo comenzar con o terminar con
BrDaHa
@BrDaHa puede usar 'in' para contiene. si 'cadena' en la lista:
Shekhar Samanta
@ShekharSamanta seguro, pero eso no resuelve el problema de verificar si una de las múltiples cosas está en una cadena, que es de lo que se trataba la pregunta original.
BrDaHa
Sí, en ese caso podemos usar: if any (element in string.split ('any delmiter') para element in list) y para string if any (element in string for element in list)
Shekhar Samanta
21

Es mejor analizar la URL correctamente, de esta manera puede manejar http://.../file.doc?fooy http://.../foo.doc/file.execorrectamente.

from urlparse import urlparse
import os
path = urlparse(url_string).path
ext = os.path.splitext(path)[1]
if ext in extensionsToCheck:
  print(url_string)
Wladimir Palant
fuente
3

Use listas de comprensión si desea una solución de línea única. El siguiente código devuelve una lista que contiene la url_string cuando tiene las extensiones .doc, .pdf y .xls o devuelve una lista vacía cuando no contiene la extensión.

print [url_string for extension in extensionsToCheck if(extension in url_string)]

NOTA: Esto es solo para verificar si contiene o no y no es útil cuando se desea extraer la palabra exacta que coincida con las extensiones.

psun
fuente
Esto es más legible que la anysolución, en mi opinión, es una de las mejores soluciones posibles para esa pregunta.
Dmitry Verhoturov
En any()mi opinión, esta es superior a la solución porque también se puede modificar para devolver el valor de coincidencia específico, así: print [extension for extension in extensionsToCheck if(extension in url_string)](vea mi respuesta para obtener detalles adicionales y cómo extraer la palabra coincidente , así como el patrón de la url_string)
Dannid el
2

Comprueba si coincide con esta expresión regular:

'(\.pdf$|\.doc$|\.xls$)'

Nota: si sus extensiones no están al final de la URL, elimine los $caracteres, pero lo debilita ligeramente


fuente
1
Es una URL, ¿qué pasa si tiene una cadena de consulta?
Wladimir Palant
import re re.search (pattern, your_string)
juankysmith
Si bien esta respuesta funciona para el caso especificado, no es escalable ni genérica. necesitarías una expresión regular larga para cada patrón que quieras hacer coincidir.
Dannid
1

Esta es una variante de la respuesta de comprensión de la lista dada por @psun.

Al cambiar el valor de salida, en realidad puede extraer el patrón de coincidencia de la comprensión de la lista (algo que no es posible con el any()enfoque de @ Lauritz-v-Thaulow)

extensionsToCheck = ['.pdf', '.doc', '.xls']
url_string = 'http://.../foo.doc'

print [extension for extension in extensionsToCheck if(extension in url_string)]

['.doc'] `

Además, puede insertar una expresión regular si desea recopilar información adicional una vez que se conoce el patrón coincidente (esto podría ser útil cuando la lista de patrones permitidos es demasiado larga para escribir en un solo patrón de expresiones regulares)

print [re.search(r'(\w+)'+extension, url_string).group(0) for extension in extensionsToCheck if(extension in url_string)]

['foo.doc']

Dannid
fuente