Проверьте, заканчивается ли строка одной из строк из списка

220

Каков питонный способ написания следующего кода?

extensions = ['.mp3','.avi']
file_name = 'test.mp3'

for extension in extensions:
    if file_name.endswith(extension):
        #do stuff

У меня есть смутное воспоминание, что явного объявления forцикла можно избежать и записать в ifусловии. Это правда?

TheMeaningfulEngineer
источник
2
Хотя на этот вопрос хорошо ответили, возможно, автор изначально задумался if any((file_name.endswith(ext) for ext in extensions)).
Сафт

Ответы:

450

Хотя str.endswith не очень широко известен, он также принимает кортеж. Вам не нужно зацикливаться.

>>> 'test.mp3'.endswith(('.mp3', '.avi'))
True
falsetru
источник
10
Вы знаете, почему он не принимает список, но делает кортеж? просто любопытно
ilyail3
2
@falsetru Ссылка в ответе не дает четкого ответа на этот вопрос. В нем только упоминается, что он может принимать кортежи, но не почему он не может принимать списки. Поскольку они обе являются последовательностями, единственное различие, которое я могу видеть, состоит в том, что списки являются изменяемыми, а кортежи неизменными. Я могу ошибаться, но я не вижу никакой другой причины, по которой это прямо указано.
KymikoLoco
4
Если вы хотите проверить, заканчивается ли строка буквой:import string; str.endswith(tuple(string.ascii_lowercase))
Алекс Виллисон
3
только примечание, endswithпринимает кортеж только для Python 2.5 и выше
Акаш Сингх
1
Никогда этого не знал! Отлично!
fool4jesus
46

Просто используйте:

if file_name.endswith(tuple(extensions)):
Джон Клементс
источник
Просто и эффективно!
Ced
6

Возьмите расширение из файла и посмотрите, есть ли оно в наборе расширений:

>>> import os
>>> extensions = set(['.mp3','.avi'])
>>> file_name = 'test.mp3'
>>> extension = os.path.splitext(file_name)[1]
>>> extension in extensions
True

Использование набора, потому что сложность времени для поиска в наборах составляет O (1) ( документы ).

alecxe
источник
8
Просто отметим, что, как вы упомянули, эффективность для довольно коротких кортежей .endswith()с интернированным кортежем будет быстрее, чем поиск по множеству
Джон Клементс
@JonClements Я думаю, вам нужен особый золотой значок комментария SO, чтобы делать отличные заметки об ответах и ​​вопросах :)
alecxe
Нет, я просто иду за значком "Подглядывающий алекс";)
Джон Клементс
2
Также обратите внимание, что в версии 2.7 и новее вы можете использовать математический синтаксис для множеств, {'.mp3','.avi'}это позволяет избежать дополнительного преобразования типов и может быть более читабельным в зависимости от вашего фона («Хотя это может вызвать путаницу со словарями и не может быть использовано для создания пустых»). наборы).
Перкинс
@JonClements когда-нибудь я стану таким же мудрым, как ты :)
alecxe
3

Есть два способа: регулярные выражения и строковые (str) методы.

Строковые методы обычно быстрее (~ 2x).

import re, timeit
p = re.compile('.*(.mp3|.avi)$', re.IGNORECASE)
file_name = 'test.mp3'
print(bool(t.match(file_name))
%timeit bool(t.match(file_name)

792 нс ± 1,83 нс на цикл (среднее ± стандартное отклонение из 7 циклов, 1000000 циклов в каждом)

file_name = 'test.mp3'
extensions = ('.mp3','.avi')
print(file_name.lower().endswith(extensions))
%timeit file_name.lower().endswith(extensions)

274 нс ± 4,22 нс на цикл (среднее ± стандартное отклонение 7 циклов, 1000000 циклов в каждом)

Игорь А
источник
1

У меня есть это:

def has_extension(filename, extension):

    ext = "." + extension
    if filename.endswith(ext):
        return True
    else:
        return False
Томас Воутерс
источник
1
Вы имеете в виду return filename.endswith(ext)? : P
Mr_and_Mrs_D
1

Я только сталкивался с этим, ища что-то еще.

Я бы порекомендовал пойти с методами в osпакете. Это потому, что вы можете сделать это более общим, компенсируя любой странный случай.

Вы можете сделать что-то вроде:

import os

the_file = 'aaaa/bbbb/ccc.ddd'

extensions_list = ['ddd', 'eee', 'fff']

if os.path.splitext(the_file)[-1] in extensions_list:
    # Do your thing.
Xxxo
источник
0

Другой возможностью может быть использование оператора IN:

extensions = ['.mp3','.avi']
file_name  = 'test.mp3'
if "." in file_name and file_name[file_name.rindex("."):] in extensions:
    print(True)
NeverHopeless
источник
@ Rainald62, indexдолжно быть rindexв этом случае.
NeverHopeless
0

Другой способ, который может вернуть список совпадающих строк:

sample = "alexis has the control"
matched_strings = filter(sample.endswith, ["trol", "ol", "troll"])
print matched_strings
['trol', 'ol']
Акаш Сингх
источник