ตรวจสอบว่าสตริงลงท้ายด้วยหนึ่งในสตริงจากรายการ


220

วิธีการเขียนแบบต่อเนื่องของไพ ธ อนคืออะไร?

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

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

ฉันมีหน่วยความจำที่คลุมเครือว่าการประกาศforลูปที่ชัดเจนสามารถหลีกเลี่ยงและเขียนในifสภาพ มันเป็นเรื่องจริงเหรอ?


2
if any((file_name.endswith(ext) for ext in extensions))แม้ว่าคำถามนี้เป็นคำตอบที่ดีบางทีผู้เขียนคิดเดิมของ
sapht

คำตอบ:


450

แม้ว่าจะไม่เป็นที่รู้จักอย่างแพร่หลายstr.endswithก็ยอมรับ tuple เช่นกัน คุณไม่จำเป็นต้องวนซ้ำ

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

10
คุณรู้ไหมว่าทำไมมันถึงไม่ยอมรับรายการ แต่เป็นสิ่งอันดับ? แค่อยากรู้อยากเห็น
ilyail3

2
@falsetru ลิงก์ในคำตอบไม่ได้ตอบคำถามนั้นอย่างชัดเจน เพียงกล่าวว่าสามารถรับสิ่งอันดับ แต่ไม่ใช่เหตุผลที่ไม่สามารถรับรายการได้ เนื่องจากทั้งสองมีลำดับความแตกต่างเดียวที่ฉันเห็นคือรายการไม่แน่นอนในขณะที่ tuples ไม่เปลี่ยนรูป ฉันอาจจะผิด แต่ฉันไม่สามารถมองเห็นเหตุผลอื่นได้ว่าเหตุใดจึงระบุไว้อย่างชัดเจน
KymikoLoco

4
หากคุณต้องการตรวจสอบว่าสตริงลงท้ายด้วยตัวอักษร:import string; str.endswith(tuple(string.ascii_lowercase))
อเล็กซ์วิลลิสัน

3
เพียงโน้ตendswithยอมรับ tuple เฉพาะสำหรับ python 2.5 ขึ้นไป
Akash Singh

1
ไม่เคยรู้เรื่องนี้! มันสมบูรณ์แบบ!
fool4jesus


6

ใช้นามสกุลจากไฟล์และดูว่ามันอยู่ในชุดของนามสกุล:

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

การใช้ชุดเนื่องจากความซับซ้อนของเวลาสำหรับการค้นหาในชุดคือ O (1) ( เอกสาร )


8
เพียงแค่ให้ความสนใจเมื่อคุณพูดถึงประสิทธิภาพสำหรับสิ่งอันดับสั้น ๆ ที่.endswith()มี tuple ภายในจะเร็วกว่าการค้นหาชุด
Jon Clements

@JonClements ฉันคิดว่าคุณต้องมีความพิเศษเพื่อแสดงความคิดเห็นทองตราสำหรับการทำบันทึกที่น่ากลัวกับคำตอบและคำถาม :)
alecxe

Nah - ฉันแค่ไปหาตรา "Stalking alecxe";)
Jon Clements

2
ยังทราบว่าใน 2.7 และใหม่กว่าคุณสามารถเราไวยากรณ์คณิตศาสตร์สำหรับชุด{'.mp3','.avi'}ก็หลีกเลี่ยงการแปลงชนิดพิเศษและอาจจะอ่านได้มากขึ้นทั้งนี้ขึ้นอยู่กับพื้นหลังของคุณ (แม้ว่ามันจะสามารถทำให้เกิดความสับสนกับพจนานุกรมและไม่สามารถนำมาใช้ในการสร้างที่ว่างเปล่า ชุด)
Perkins

@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 ns ± 1.83 ns ต่อวง (หมายถึง± std. dev. ของ 7 วิ่ง 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 ต่อวง (หมายถึง± std. dev. จาก 7 วิ่ง, 1000000 ลูปแต่ละอัน)



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.

0

ความเป็นไปได้อีกอย่างหนึ่งคือการใช้ประโยชน์จากคำสั่ง IN:

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

@ Rainald62 indexควรเป็นrindexเช่นนั้น
NeverHopeless

0

อีกวิธีหนึ่งซึ่งสามารถส่งคืนรายการของสตริงที่ตรงกันได้

sample = "alexis has the control"
matched_strings = filter(sample.endswith, ["trol", "ol", "troll"])
print matched_strings
['trol', 'ol']
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.