Come verificare se una stringa contiene un elemento da un elenco in Python


218

Ho qualcosa del genere:

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

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

Mi chiedo quale sarebbe il modo più elegante per farlo in Python (senza usare il ciclo for)? Stavo pensando a qualcosa del genere (come da C / C ++), ma non ha funzionato:

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

Modifica: sono un po 'costretto a spiegare in che modo questo è diverso dalla domanda di seguito che è contrassegnata come potenziale duplicato (quindi credo che non si chiuda).

La differenza è che volevo verificare se una stringa fa parte di un elenco di stringhe, mentre l'altra domanda sta verificando se una stringa da un elenco di stringhe è una sottostringa di un'altra stringa. Simile, ma non è la stessa cosa e la semantica è importante quando stai cercando una risposta IMHO online. Queste due domande stanno effettivamente cercando di risolvere il problema opposto l'una dell'altra. La soluzione per entrambi risulta essere la stessa però.


Risposte:


422

Utilizzare un generatore insieme any, con i cortocircuiti sul primo vero:

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

EDIT: vedo che questa risposta è stata accettata dall'OP. Sebbene la mia soluzione possa essere una soluzione "abbastanza buona" per il suo problema specifico, ed è un buon modo generale per verificare se si trovano stringhe in un elenco in un'altra stringa, tenere presente che è tutto ciò che questa soluzione fa. Non importa DOVE la stringa si trova ad es. Alla fine della stringa . Se questo è importante, come spesso accade con gli URL, dovresti cercare la risposta di @Wladimir Palant o rischi di ottenere falsi positivi.


1
questo era esattamente quello che stavo cercando. nel mio caso non importa dove nella stringa si trova l'estensione. grazie
pootzko il

Ottimo consiglio Usando questo esempio, è così che controllo se uno degli argomenti fa maturare i ben noti flag di aiuto: any ([x.lower () in ['-?', '- h', '- help', '/ h '] for x in sys.argv [1:]])
AX Labs,

@ AX-Labs utilizzando la comprensione dell'elenco all'interno anyannulla alcuni dei possibili guadagni che fornisce il corto circuito, perché l'intero elenco dovrà essere costruito in ogni caso. Se si utilizza l'espressione senza parentesi quadre ( any(x.lower() in ['-?','-h','--help', '/h'] for x in sys.argv[1:])), la x.lower() in [...]parte verrà valutata solo fino a quando non viene trovato un valore True.
Lauritz V. Thaulow,

5
E se voglio sapere cos'è ext quando any () restituisce True?
Peter Senna,

@PeterSenna: any()restituirà solo vero o falso , ma vedi la risposta di comprensione dell'elenco di @psun di seguito con questa modifica: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

5
questo è intelligente - non sapevo che le tuple potessero farlo! Ma funziona solo quando la sottostringa è ancorata a un'estremità della stringa.
Dannid,

3
Molto bello. Vorrei solo che ci fosse qualcosa come "contiene" piuttosto che solo l'inizio o la fine
BrDaHa,

@BrDaHa puoi usare 'in' per contiene. se "stringa" nell'elenco:
Shekhar Samanta,

@ShekharSamanta certo, ma questo non risolve il problema di verificare se una o più cose sono in una stringa, che è la domanda originale.
BrDaHa,

Sì, in quel caso possiamo usare: if any (element in string.split ('any delmiter') per element in list) e per string if any (element in string per element in list)
Shekhar Samanta

21

È meglio analizzare correttamente l'URL: in questo modo è possibile gestirlo http://.../file.doc?fooe http://.../foo.doc/file.execorrettamente.

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

3

Utilizzare la comprensione dell'elenco se si desidera una soluzione a riga singola. Il codice seguente restituisce un elenco contenente url_string quando ha le estensioni .doc, .pdf e .xls o restituisce un elenco vuoto quando non contiene l'estensione.

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

NOTA: Questo serve solo a verificare se contiene o meno e non è utile quando si desidera estrarre la parola esatta corrispondente alle estensioni.


Questa è più leggibile della anysoluzione, secondo me è una delle migliori soluzioni possibili per quella domanda.
Dmitry Verhoturov,

Questo è superiore alla any()soluzione secondo me perché può essere modificato per restituire anche il valore di corrispondenza specifico, in questo modo: print [extension for extension in extensionsToCheck if(extension in url_string)](vedi la mia risposta per ulteriori dettagli e come estrarre la parola di corrispondenza e il modello da url_string)
Dannid,

2

Controlla se corrisponde a questa regex:

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

Nota: se le estensioni non si trovano alla fine dell'URL, rimuovi i $caratteri, ma lo indebolisce leggermente


1
È un URL, cosa succede se ha una stringa di query?
Wladimir Palant,

import re re.search (pattern, your_string)
juankysmith

mentre questa risposta funziona per il caso specificato, non è scalabile o generica. avresti bisogno di una regex lunga per ogni modello che desideri abbinare.
Dannid,

1

Questa è una variante della risposta di comprensione dell'elenco fornita da @psun.

Cambiando il valore di output, puoi effettivamente estrarre il modello di corrispondenza dalla comprensione dell'elenco (cosa impossibile con l' any()approccio di @ Lauritz-v-Thaulow)

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

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

[ '.Doc'] `

È inoltre possibile inserire un'espressione regolare se si desidera raccogliere ulteriori informazioni una volta noto il modello corrispondente (ciò potrebbe essere utile quando l'elenco dei modelli consentiti è troppo lungo per scrivere in un singolo modello regex)

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

['foo.doc']

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.