Jak sprawdzić, czy ciąg znaków zawiera element z listy w Pythonie

217

Mam coś takiego:

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

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

Zastanawiam się, jaki byłby bardziej elegancki sposób na to w Pythonie (bez użycia pętli for)? Myślałem o czymś takim (jak z C / C ++), ale to nie działało:

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

Edycja: Jestem trochę zmuszony do wyjaśnienia, w jaki sposób różni się to od pytania poniżej, które jest oznaczone jako potencjalny duplikat (więc chyba nie można go zamknąć).

Różnica polega na tym, że chciałem sprawdzić, czy ciąg znaków jest częścią jakiejś listy ciągów, podczas gdy drugim pytaniem jest sprawdzenie, czy ciąg znaków z listy ciągów jest podciągiem innego ciągu. Podobne, ale niezupełnie takie same i semantyka mają znaczenie, gdy szukasz odpowiedzi online IMHO. Te dwa pytania mają na celu rozwiązanie przeciwnego problemu. Rozwiązanie dla obu okazuje się jednak takie samo.

pootzko
źródło
4
Możliwy duplikat Sprawdź, czy istnieje wiele ciągów w innym ciągu
GingerPlusPlus

Odpowiedzi:

420

Użyj razem generatora any, który zwiera pierwsze True:

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

EDYCJA: Widzę, że odpowiedź została zaakceptowana przez OP. Chociaż moje rozwiązanie może być „wystarczająco dobrym” rozwiązaniem jego konkretnego problemu i jest dobrym ogólnym sposobem sprawdzenia, czy jakieś ciągi na liście znajdują się w innym ciągu, pamiętaj, że to wszystko, co robi to rozwiązanie. Nie ma znaczenia GDZIE znaleziono łańcuch, np. Na końcu łańcucha . Jeśli jest to ważne, jak to często bywa z adresami URL, powinieneś spojrzeć na odpowiedź @Wladimir Palant, albo ryzykujesz uzyskanie fałszywych wyników pozytywnych.

Lauritz V. Thaulow
źródło
1
właśnie tego szukałem. w moim przypadku nie ma znaczenia, gdzie w ciągu znajduje się rozszerzenie. dzięki
pootzko
Świetna sugestia. W tym przykładzie sprawdzam, czy którykolwiek z argumentów odpowiada dobrze znanym flagom pomocy: any ([x.lower () w ['-?', '- h', '- help', '/ h '] dla x w sys.argv [1:]])
AX Labs
@ AX-Labs korzystający ze zrozumień list wewnątrz anyzaprzecza niektórym możliwym korzyściom, jakie zapewnia zwarcie, ponieważ za każdym razem trzeba będzie zbudować całą listę. Jeśli użyjesz wyrażenia bez nawiasów kwadratowych ( any(x.lower() in ['-?','-h','--help', '/h'] for x in sys.argv[1:])), x.lower() in [...]część będzie oceniana tylko do momentu znalezienia wartości True.
Lauritz V. Thaulow
5
A jeśli chcę wiedzieć, co to jest ext, gdy którykolwiek () zwraca True?
Peter Senna
@PeterSenna: any()zwróci tylko prawdę lub fałsz , ale patrz poniższa lista odpowiedzi print [extension for extension in extensionsToCheck if(extension in url_string)]
@psun
45
extensionsToCheck = ('.pdf', '.doc', '.xls')

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

'test.jpg'.endswith(extensionsToCheck)   # returns False
eumiro
źródło
5
ten jest sprytny - nie wiedziałem, że krotki mogą to zrobić !, ale działa tylko wtedy, gdy twój podciąg jest zakotwiczony na jednym końcu łańcucha.
Dannid,
3
Świetnie. Chciałbym, żeby było coś takiego jak „zawiera”, a nie tylko zaczyna się lub kończy
BrDaHa
@BrDaHa, którego możesz użyć „w” dla zawiera. jeśli „string” na liście:
Shekhar Samanta
@ShekharSamanta na pewno, ale to nie rozwiązuje problemu sprawdzania, czy jedna z wielu rzeczy jest w ciągu, czyli pierwotne pytanie.
BrDaHa
Tak, w takim przypadku możemy użyć: if any (element in string.split ('any delmiter') dla elementu na liście) i string jeśli istnieje (element w łańcuchu dla elementu na liście)
Shekhar Samanta
21

Lepiej jest poprawnie parsować adres URL - w ten sposób możesz obsługiwać http://.../file.doc?fooi http://.../foo.doc/file.exepoprawnie.

from urlparse import urlparse
import os
path = urlparse(url_string).path
ext = os.path.splitext(path)[1]
if ext in extensionsToCheck:
  print(url_string)
Władimir Palant
źródło
3

Użyj wyrażeń listowych, jeśli chcesz rozwiązania z pojedynczą linią. Poniższy kod zwraca listę zawierającą łańcuch url, gdy ma rozszerzenia .doc, .pdf i .xls lub zwraca pustą listę, gdy nie zawiera rozszerzenia.

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

UWAGA: Służy to tylko sprawdzeniu, czy zawiera lub nie, i nie jest użyteczne, gdy chce się wyodrębnić dokładne słowo pasujące do rozszerzeń.

psun
źródło
Jest to bardziej czytelne niż anyrozwiązanie, moim zdaniem jedno z najlepszych możliwych rozwiązań tego pytania.
Dmitry Verhoturov
any()Moim zdaniem ten jest lepszy od rozwiązania, ponieważ można go zmienić tak, aby zwracał również określoną wartość dopasowania, na przykład: print [extension for extension in extensionsToCheck if(extension in url_string)](zobacz moją odpowiedź, aby uzyskać dodatkowe szczegóły i jak wyodrębnić pasujące słowo oraz wzorzec z url_string)
Dannid,
2

Sprawdź, czy pasuje do tego wyrażenia regularnego:

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

Uwaga: jeśli rozszerzenia nie znajdują się na końcu adresu URL, usuń $znaki, ale nieco go osłabi


źródło
1
To adres URL, a jeśli ma ciąg zapytania?
Wladimir Palant
import re re.search (pattern, your_string)
juankysmith
chociaż ta odpowiedź działa w określonym przypadku, nie jest skalowalna ani ogólna. będziesz potrzebować długiego wyrażenia regularnego dla każdego wzoru, który chcesz dopasować.
Dannid,
1

Jest to wariant odpowiedzi na listę podanej przez @psun.

Przełączając wartość wyjściową, możesz faktycznie wyodrębnić pasujący wzorzec ze zrozumienia listy (coś nie jest możliwe przy any()podejściu @ Lauritz-v-Thaulow)

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

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

['.doc'] `

Ponadto możesz wstawić wyrażenie regularne, jeśli chcesz zebrać dodatkowe informacje, gdy znany jest dopasowany wzorzec (może to być przydatne, gdy lista dozwolonych wzorców jest zbyt długa, aby zapisać w jednym wzorcu wyrażenia regularnego)

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

['foo.doc']

Dannid
źródło