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.


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.


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

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)

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ń.


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


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']

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.