Como verificar se uma string contém um elemento de uma lista em Python

217

Eu tenho algo parecido com isto:

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

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

Eu estou querendo saber qual seria a maneira mais elegante de fazer isso no Python (sem usar o loop for)? Eu estava pensando em algo assim (como em C / C ++), mas não funcionou:

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

Edit: Eu sou meio que forçado a explicar como isso é diferente da pergunta abaixo, que está marcada como potencial duplicada (para que não fique fechada, eu acho).

A diferença é que eu queria verificar se uma string faz parte de alguma lista de strings, enquanto a outra pergunta é verificar se uma string de uma lista de strings é uma substring de outra string. Semelhante, mas não exatamente o mesmo, e a semântica importa quando você procura uma resposta on-line IMHO. Essas duas perguntas estão realmente procurando resolver o problema oposto um do outro. A solução para ambos acaba sendo a mesma.

pootzko
fonte
4
Possível duplicado de Verifique se existem múltiplas cadeias em outra seqüência
GingerPlusPlus

Respostas:

418

Use um gerador junto com o anyqual curto-circuito no primeiro True:

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

EDIT: Vejo que esta resposta foi aceita pelo OP. Embora minha solução possa ser "boa o suficiente" para o seu problema específico e seja uma boa maneira geral de verificar se alguma string de uma lista foi encontrada em outra string, lembre-se de que isso é tudo o que essa solução faz. Não importa ONDE a cadeia é encontrada, por exemplo, no final da cadeia . Se isso é importante, como geralmente acontece com os URLs, você deve procurar a resposta de @Wladimir Palant, ou corre o risco de obter falsos positivos.

Lauritz V. Thaulow
fonte
1
era exatamente isso que eu estava procurando. no meu caso, não importa onde na sequência está a extensão. graças
pootzko
Ótima sugestão. Usando este exemplo, é assim que eu verifico se algum dos argumentos corresponde aos sinalizadores de ajuda conhecidos: any ([x.lower () em ['-?', '- h', '- help', '/ h '] para x em sys.argv [1:]])
AX Labs
O @ AX-Labs, usando a compreensão da lista any, negará alguns dos possíveis ganhos que o curto-circuito fornece, porque a lista inteira terá que ser construída em todos os casos. Se você usar a expressão sem colchetes ( any(x.lower() in ['-?','-h','--help', '/h'] for x in sys.argv[1:])), a x.lower() in [...]peça será avaliada apenas até que um valor True seja encontrado.
Lauritz V. Thaulow
5
E se eu quiser saber o que é ext quando any () retorna True?
Peter
@ PeterSenna: any()retornará apenas verdadeiro ou falso , mas veja a resposta de compreensão da lista do @psun abaixo com esta modificação: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
fonte
5
este é inteligente - eu não sabia que as tuplas poderiam fazer isso !, mas só funciona quando sua substring está ancorada a uma extremidade da string.
Dannid
3
Forma legal. Eu só gostaria que houvesse algo como "contém" em vez de apenas startswith ou endswith
BrDaHa
@BrDaHa você pode usar 'in' para contains. if 'string' na lista:
Shekhar Samanta
@ShekharSamanta com certeza, mas isso não resolve o problema de verificar se uma das várias coisas está em uma string, que é a questão original.
BrDaHa
Sim, nesse caso, podemos usar: if any (elemento em string.split ('any delmiter') para elemento na lista) & for string if any (elemento em seqüência de caracteres para elemento na lista)
Shekhar Samanta
21

É melhor analisar o URL corretamente - dessa forma, você pode lidar com isso http://.../file.doc?fooe http://.../foo.doc/file.execorretamente.

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
fonte
3

Use a compreensão da lista se desejar uma solução de linha única. O código a seguir retorna uma lista que contém a url_string quando possui as extensões .doc, .pdf e .xls ou retorna uma lista vazia quando não contém a extensão.

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

NOTA: Isso serve apenas para verificar se ele contém ou não e não é útil quando se deseja extrair a palavra exata que corresponde às extensões.

psun
fonte
Isso é mais legível que a anysolução, na minha opinião, é uma das melhores soluções possíveis para essa pergunta.
Dmitry Verhoturov 08/09/16
Este é superior à any()solução, na minha opinião, porque pode ser alterado para retornar também o valor de correspondência específico, da seguinte forma: print [extension for extension in extensionsToCheck if(extension in url_string)](veja minha resposta para obter detalhes adicionais e como extrair a palavra correspondente e o padrão da url_string)
Dannid
2

Verifique se ele corresponde a este regex:

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

Nota: se as extensões não estiverem no final do URL, remova os $caracteres, mas o enfraquece um pouco


fonte
1
É uma URL, e se tiver uma sequência de consultas?
Wladimir Palant
import re re.search (padrão, your_string)
juankysmith
Embora essa resposta funcione para o caso especificado, ela não é escalável ou genérica. você precisaria de uma regex longa para cada padrão que deseja corresponder.
Dannid
1

Esta é uma variante da resposta de compreensão da lista dada por @psun.

Ao alternar o valor de saída, é possível extrair o padrão de correspondência da compreensão da lista (algo que não é possível com a any()abordagem 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'] `

Além disso, você pode inserir uma expressão regular se desejar coletar informações adicionais assim que o padrão correspondente for conhecido (isso pode ser útil quando a lista de padrões permitidos for muito longa para gravar em um único padrão regex)

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

['foo.doc']

Dannid
fonte