Kiểm tra xem chuỗi kết thúc bằng một trong các chuỗi từ danh sách


220

Cách viết pythonic của mã sau đây là gì?

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

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

Tôi có một bộ nhớ mơ hồ rằng việc khai báo rõ ràng về forvòng lặp có thể tránh được và được viết trong ifđiều kiện. Điều này có đúng không?


2
Mặc dù câu hỏi này được trả lời tốt, nhưng có lẽ ban đầu tác giả nghĩ đến if any((file_name.endswith(ext) for ext in extensions)).
sapht

Câu trả lời:


450

Mặc dù không được biết đến rộng rãi, str.endswith cũng chấp nhận một tuple. Bạn không cần phải lặp.

>>> 'test.mp3'.endswith(('.mp3', '.avi'))
True

10
Bạn có biết tại sao nó sẽ không chấp nhận một danh sách nhưng một tuple không? chỉ tò mò
ilyail3

2
@falsetru Liên kết trong câu trả lời không trả lời rõ ràng câu hỏi đó. Nó chỉ đề cập rằng nó có thể chấp nhận bộ dữ liệu, nhưng không phải tại sao nó không thể chấp nhận danh sách. Vì cả hai đều là trình tự, sự khác biệt duy nhất tôi có thể thấy là các danh sách có thể thay đổi, trong khi các bộ dữ liệu là bất biến. Tôi có thể sai, nhưng tôi không thể thấy bất kỳ lý do nào khác tại sao điều đó được nêu rõ ràng.
KymikoLoco

4
Nếu bạn muốn kiểm tra xem một chuỗi kết thúc bằng một chữ cái:import string; str.endswith(tuple(string.ascii_lowercase))
Alex Willison

3
chỉ là một ghi chú, chỉ endswithchấp nhận tuple cho python 2.5 trở lên
Akash Singh

1
Chưa bao giờ biết điều này! Thật hoàn hảo!
lừa4jesus


6

Lấy một phần mở rộng từ tệp và xem nếu nó nằm trong bộ tiện ích mở rộng:

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

Sử dụng một bộ vì độ phức tạp thời gian để tra cứu trong các bộ là O (1) ( tài liệu ).


8
Chỉ cần lưu ý khi bạn đề cập đến hiệu quả, đối với các bộ dữ liệu khá ngắn, .endswith()với một bộ dữ liệu được thực hiện sẽ nhanh hơn một bộ tra cứu
Jon Clements

@JonClements Tôi nghĩ rằng bạn cần một huy hiệu bình luận vàng SO đặc biệt để ghi chú tuyệt vời cho câu trả lời và câu hỏi :)
alecxe

Nah - Tôi chỉ dùng huy hiệu "Stalking alecxe";)
Jon Clements

2
Cũng lưu ý rằng trong 2.7 và mới hơn, bạn có thể sử dụng cú pháp toán học cho các bộ, {'.mp3','.avi'}nó tránh chuyển đổi loại thêm và có thể dễ đọc hơn tùy thuộc vào nền của bạn ('Mặc dù nó có thể gây nhầm lẫn với từ điển và không thể được sử dụng để tạo trống bộ).
Perkins

@JonClements một ngày nào đó tôi sẽ trở nên khôn ngoan như bạn :)
alecxe

3

Có hai cách: biểu thức chính quy và phương thức chuỗi (str).

Các phương thức chuỗi thường nhanh hơn (~ 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 mỗi vòng lặp (trung bình ± std. Dev của 7 lần chạy, mỗi vòng 1000000)

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

274 ns ± 4,22 ns mỗi vòng lặp (trung bình ± std. Dev của 7 lần chạy, mỗi vòng 1000000)


1

Tôi có cái này:

def has_extension(filename, extension):

    ext = "." + extension
    if filename.endswith(ext):
        return True
    else:
        return False

1
Ý bạn là return filename.endswith(ext)sao? : P
Mr_and_Mrs_D

1

Tôi vừa đi qua cái này, trong khi tìm kiếm thứ khác.

Tôi sẽ khuyên bạn nên đi với các phương pháp trong osgói. Điều này là do bạn có thể làm cho nó chung chung hơn, bù đắp cho bất kỳ trường hợp kỳ lạ nào.

Bạn có thể làm một cái gì đó như:

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.

0

Một khả năng khác có thể là sử dụng câu lệnh IN:

extensions = ['.mp3','.avi']
file_name  = 'test.mp3'
if "." in file_name and file_name[file_name.rindex("."):] in extensions:
    print(True)

@ Rainald62, indexnên rindextrong trường hợp đó.
NeverHopless

0

một cách khác có thể trả về danh sách các chuỗi phù hợp là

sample = "alexis has the control"
matched_strings = filter(sample.endswith, ["trol", "ol", "troll"])
print matched_strings
['trol', 'ol']
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.