Як перевірити, чи містить рядок елемент зі списку в Python


217

У мене є щось подібне:

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

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

Мені цікаво, який би був більш елегантний спосіб зробити це в Python (не використовуючи цикл for)? Я думав про щось подібне (наприклад, від C / C ++), але це не вийшло:

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

Редагувати: Я начебто змушений пояснювати, як це відрізняється від питання, яке нижче позначене як потенційний дублікат (тому я не думаю, що він закривається).

Різниця полягає в тому, що я хотів перевірити, чи рядок є частиною списку рядків, тоді як іншим питанням є перевірка того, чи є рядок зі списку рядків підрядком іншої рядки. Подібні, але не зовсім однакові і семантичні значення мають значення, коли ви шукаєте відповідь в Інтернеті IMHO. Ці два питання насправді шукають для вирішення протилежної проблеми один одного. Однак рішення для обох виявляється однаковим.


Відповіді:


420

Використовуйте генератор разом з any, який має коротке замикання на першому True:

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

EDIT: Я бачу, що ця відповідь була прийнята ОП. Хоча моє рішення може бути "досить хорошим" рішенням його конкретної проблеми, і це хороший загальний спосіб перевірити, чи є якісь рядки в списку в іншій рядку, майте на увазі, що це все, що це рішення робить. Це неважливо, де знаходиться рядок, наприклад, у кінці рядка . Якщо це важливо, як це часто трапляється з URL-адресами, слід звернутися до відповіді @Wladimir Palant, або ви ризикуєте отримати помилкові позитиви.


1
саме це я і шукав. в моєму випадку не має значення, де в рядку знаходиться розширення. дякую
pootzko

Чудова пропозиція. Використовуючи цей приклад, я перевіряю, чи будь-який з аргументів відповідає загальновідомим прапорам довідки: any ([x.lower () в ['-?', '- h', '- help', '/ h '] для x in sys.argv [1:]])
AX Labs

@ AX-Labs, що використовує розуміння списку всередині any, заперечує деякі можливі вигоди від короткого замикання, оскільки весь список повинен бути побудований у кожному випадку. Якщо ви використовуєте вираз без квадратних дужок ( any(x.lower() in ['-?','-h','--help', '/h'] for x in sys.argv[1:])), x.lower() in [...]частина буде оцінюватися лише до того, як буде знайдено значення True.
Лауріц В. Таулов

5
І якщо я хочу знати, що таке ext, коли any () повертає True?
Пітер Сенна

@PeterSenna: any()поверне лише істинне чи неправдиве , але див. Відповідь щодо списку @psun нижче з цією модифікацією: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
цей розумний - я не знав, що кортежі можуть це зробити !, але він працює лише тоді, коли ваша підрядка прикріплена до одного кінця рядка.
Даннід

3
Спокійно. Я просто хочу, щоб було щось на кшталт "містить", а не просто startwith або endwith
BrDaHa

@BrDaHa ви можете використовувати "in" для містить. якщо 'рядок' у списку:
Shekhar Samanta

@ShekharSamanta впевнений, але це не вирішує проблему перевірки, чи є одна з декількох речей у рядку, а саме про те, що було в початковому питанні.
BrDaHa

Так, у цьому випадку ми можемо використовувати: якщо такий (елемент у string.split ("будь-який дельмітер") для елемента в списку) та для рядка, якщо такий є (елемент у рядку для елемента в списку)
Шехар Саманта

21

Краще правильно розібрати URL-адресу - таким чином ви зможете правильно http://.../file.doc?fooта http://.../foo.doc/file.exeправильно поводитися .

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

Використовуйте розуміння списку, якщо ви хочете вирішити одну лінію. Наступний код повертає список, що містить url_string, коли він має розширення .doc, .pdf та .xls або повертає порожній список, коли він не містить розширення.

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

ПРИМІТКА. Це лише для того, щоб перевірити, чи містить він чи ні, і не корисно, коли потрібно витягти точне слово, яке відповідає розширенням.


Це читабельніше, ніж anyрішення, на мою думку, це одне з найкращих можливих рішень цього питання.
Дмитро Верхотуров

На any()мою думку, це перевершує рішення, оскільки воно може бути змінене і для повернення конкретного відповідного значення, як-от так: print [extension for extension in extensionsToCheck if(extension in url_string)](див. Мою відповідь для отримання додаткової інформації та вилучення відповідного слова , а також шаблону з url_string)
Даннід

2

Перевірте, чи відповідає цей регулярний вираз:

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

Примітка. Якщо розширення не знаходяться в кінці URL-адреси, видаліть $символи, але це трохи послабить його


1
Це URL-адреса, а якщо в ньому є рядок запиту?
Володимир Палант

імпортувати повторний пошук (шаблон, your_string)
juankysmith

хоча ця відповідь працює для вказаного випадку, вона не є масштабованою або загальною. вам знадобиться довгий регулярний вираз для кожного шаблону, який ви хочете зіставити.
Даннід

1

Це варіант відповіді щодо розуміння списку, наданого @psun.

Перемикаючи вихідне значення, ви можете фактично дістати відповідну модель із розуміння списку (щось неможливо при any()підході @ Lauritz-v-Thaulow)

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

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

['.doc'] `

Крім того, ви можете вставити регулярний вираз, якщо хочете зібрати додаткову інформацію, коли відомий узор (це може бути корисно, коли список дозволених шаблонів занадто довгий, щоб записати в єдиний шаблон регулярного вираження)

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

['foo.doc']

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.