Periksa apakah string berakhir dengan salah satu string dari daftar

220

Apa cara pythonic dalam menulis kode berikut?

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

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

Saya memiliki memori yang tidak jelas bahwa deklarasi eksplisit dari forloop dapat dihindari dan ditulis dalam ifkondisi tersebut. Apakah ini benar?

TheMeaningfulEngineer
sumber
2
Meskipun pertanyaan ini dijawab dengan baik, mungkin penulis awalnya memikirkannya if any((file_name.endswith(ext) for ext in extensions)).
sapht

Jawaban:

450

Meskipun tidak dikenal secara luas, str.endswith juga menerima tuple. Anda tidak perlu mengulang.

>>> 'test.mp3'.endswith(('.mp3', '.avi'))
True
falsetru
sumber
10
apakah Anda tahu mengapa itu tidak akan menerima daftar tetapi apakah tuple? hanya ingin tahu
ilyail3
2
@ falsetru Tautan dalam jawaban tidak secara eksplisit menjawab pertanyaan itu. Itu hanya menyebutkan bahwa ia dapat menerima tupel, tetapi tidak mengapa ia tidak dapat menerima daftar. Karena keduanya merupakan urutan, satu-satunya perbedaan yang berpotensi saya lihat adalah daftar dapat berubah, sementara tupel tidak dapat diubah. Saya mungkin salah, tetapi saya tidak bisa melihat alasan lain mengapa itu dinyatakan secara eksplisit.
KymikoLoco
4
Jika Anda ingin memeriksa apakah sebuah string diakhiri dengan surat:import string; str.endswith(tuple(string.ascii_lowercase))
Alex Willison
3
hanya sebuah catatan, endswithterima tuple hanya untuk python 2.5 ke atas
Akash Singh
1
Tidak pernah tahu ini! Itu sempurna!
fool4jesus
46

Cukup gunakan:

if file_name.endswith(tuple(extensions)):
Jon Clements
sumber
Sederhana dan efektif!
Ced
6

Ambil ekstensi dari file dan lihat apakah ekstensi itu ada di set ekstensi:

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

Menggunakan set karena kompleksitas waktu untuk pencarian dalam set adalah O (1) ( docs ).

alecxe
sumber
8
Hanya untuk catatan seperti yang Anda sebutkan efisiensi, untuk tupel cukup singkat, yang .endswith()dengan tupel diinternir akan lebih cepat dari satu set lookup
Jon Clements
@JonClements Saya pikir Anda perlu lencana komentar emas SO khusus untuk membuat catatan yang luar biasa pada jawaban dan pertanyaan :)
alecxe
Nah - aku hanya akan untuk "Stalking alecxe" lencana;)
Jon Clements
2
Perhatikan juga bahwa pada 2.7 dan yang lebih baru, Anda dapat menggunakan sintaks matematika untuk set,, {'.mp3','.avi'}ia menghindari konversi tipe tambahan dan mungkin lebih mudah dibaca tergantung pada latar belakang Anda ('Meskipun dapat menyebabkan kebingungan dengan kamus, dan tidak dapat digunakan untuk membuat kosong set).
Perkins
@JonClements suatu hari nanti aku akan menjadi sama bijaknya denganmu :)
alecxe
3

Ada dua cara: ekspresi reguler dan metode string (str).

Metode string biasanya lebih cepat (~ 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 ns ± 1,83 ns per loop (rata-rata ± std. Dev dari 7 run, masing-masing 10.00000 loop)

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

274 ns ± 4,22 ns per loop (rata-rata ± std. Dev dari 7 run, masing-masing 10.00000 loop)

Igor A
sumber
1

Aku punya ini:

def has_extension(filename, extension):

    ext = "." + extension
    if filename.endswith(ext):
        return True
    else:
        return False
Thomas Wouters
sumber
1
Maksudmu return filename.endswith(ext)? : P
Mr_and_Mrs_D
1

Saya baru saja menemukan ini, sambil mencari sesuatu yang lain.

Saya akan merekomendasikan untuk pergi dengan metode dalam ospaket. Ini karena Anda bisa membuatnya lebih umum, mengimbangi kasus aneh apa pun.

Anda dapat melakukan sesuatu seperti:

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
sumber
0

Kemungkinan lain bisa menggunakan pernyataan IN:

extensions = ['.mp3','.avi']
file_name  = 'test.mp3'
if "." in file_name and file_name[file_name.rindex("."):] in extensions:
    print(True)
Tidak ada yang hilang
sumber
@ Rainald62, indexseharusnya rindexdalam kasus itu.
NeverHopeless
0

Cara lain yang dapat mengembalikan daftar string yang cocok adalah

sample = "alexis has the control"
matched_strings = filter(sample.endswith, ["trol", "ol", "troll"])
print matched_strings
['trol', 'ol']
Akash Singh
sumber