Как проверить, содержит ли строка элемент из списка в Python

218

У меня есть что-то вроде этого:

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)

Редактировать: я вынужден объяснить, как это отличается от вопроса ниже, который помечен как потенциальный дубликат (так что, я думаю, он не закрывается).

Разница в том, что я хотел проверить, является ли строка частью какого-либо списка строк, тогда как другой вопрос - проверить, является ли строка из списка строк подстрокой другой строки. Похоже, но не совсем то же самое, и семантика имеет значение, когда вы ищете ответ онлайн ИМХО. Эти два вопроса на самом деле направлены на решение противоположной проблемы друг друга. Решение для обоих оказывается одинаковым, хотя.

pootzko
источник
4
Возможный дубликат проверки
GingerPlusPlus

Ответы:

423

Вместе с генератором используйте генератор any, который замыкает первый True:

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

РЕДАКТИРОВАТЬ: Я вижу, что этот ответ был принят OP. Хотя мое решение может быть «достаточно хорошим» решением его конкретной проблемы, и это хороший общий способ проверить, найдены ли какие-либо строки в списке в другой строке, имейте в виду, что это все, что делает это решение. Неважно, где находится строка, например, в конце строки . Если это важно, как это часто бывает с URL-адресами, вам следует обратиться к ответу @Wladimir Palant, иначе вы рискуете получить ложные срабатывания.

Лауриц В. Таулов
источник
1
это было именно то, что я искал. в моем случае не имеет значения, где в строке находится расширение. спасибо
pootzko
Отличное предложение. Используя этот пример, вот как я проверяю, совпадает ли какой-либо из аргументов с хорошо известными флагами помощи: any ([x.lower () в ['-?', '- h', '- help', '/ h '] для x в 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()будет возвращать только true или false , но см. Приведенный ниже ответ @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
eumiro
источник
5
этот умный - я не знал, что кортежи могут это делать !, но он работает только тогда, когда ваша подстрока привязана к одному концу строки.
Даннид
3
Круто. Я просто хотел бы, чтобы было что-то вроде «содержит», а не только начиналось с или заканчивалось
BrDaHa
@BrDaHa вы можете использовать «в» для содержит. if 'string' в списке:
Шехар Саманта
@ShekharSamanta, конечно, но это не решает проблему проверки, есть ли одна из нескольких вещей в строке, то есть о чем был первоначальный вопрос.
BrDaHa
Да, в этом случае мы можем использовать: если есть (элемент в string.split ('any delmiter') для элемента в списке) и для строки, если есть (элемент в строке для элемента в списке)
Шекхар Саманта
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)]

ПРИМЕЧАНИЕ: это только для проверки, если оно содержит или нет, и бесполезно, когда нужно извлечь точное слово, соответствующее расширениям.

PSUN
источник
Это более читабельно, чем anyрешение, на мой взгляд, это одно из лучших возможных решений этого вопроса.
Дмитрий Верхотуров
По any()моему мнению, этот вариант превосходит решение, потому что его можно изменить, чтобы он также возвращал определенное значение соответствия, например так: print [extension for extension in extensionsToCheck if(extension in url_string)](см. Мой ответ для получения дополнительной информации и того, как извлечь соответствующее слово, а также шаблон из url_string)
Даннид
2

Проверьте, соответствует ли это регулярному выражению:

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

Примечание: если ваши расширения находятся не в конце URL, удалите $символы, но это немного ослабляет его


источник
1
Это URL, что если в нем есть строка запроса?
Владимир Палант
import re resese (pattern, 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']

Dannid
источник