นิพจน์ทั่วไป: ค้นหาในรายการ


91

ฉันต้องการกรองสตริงในรายการโดยยึดตามนิพจน์ทั่วไป

จะมีอะไรดีไปกว่า[x for x in list if r.match(x)]?

คำตอบ:


116

คุณสามารถสร้างตัววนซ้ำใน Python 3.x หรือรายการใน Python 2.x โดยใช้:

filter(r.match, list)

ในการแปลงตัววนซ้ำ Python 3.x เป็นรายการเพียงแค่ส่งมัน list(filter(..)).


2
ที่จริงแล้วความเข้าใจในรายการมักจะชอบมากกว่าโครงสร้างที่ใช้งานได้เช่นตัวกรองลดแลมด้า ฯลฯ
Ivo van der Wijk

39
@Ivo: พวกเขามักจะชอบเพราะมักจะชัดเจนและมักจะรวบรัดกว่า อย่างไรก็ตามในกรณีนี้filterเวอร์ชันมีความชัดเจนและมีเสียงรบกวนน้อยกว่ามาก
sepp2k

9
ที่r.matchนี่คืออะไร?
rbatt

2
@rbatt r.matchเป็นวิธีการที่เมื่อนำไปใช้กับสตริงที่กำหนดพบว่า regex rตรงกับสตริงนั้นหรือไม่ (และส่งคืนอ็อบเจ็กต์การจับคู่ที่ตรงกันหากเป็นเช่นนั้น แต่ไม่สำคัญในกรณีนี้เนื่องจากเราสนใจว่าผลลัพธ์จะเป็นจริงหรือไม่)
sepp2k

175

ตัวอย่างเต็ม (Python 3):
สำหรับ Python 2.x ให้ดูที่หมายเหตุด้านล่าง

import re

mylist = ["dog", "cat", "wildcat", "thundercat", "cow", "hooo"]
r = re.compile(".*cat")
newlist = list(filter(r.match, mylist)) # Read Note
print(newlist)

พิมพ์:

['cat', 'wildcat', 'thundercat']

บันทึก:

สำหรับนักพัฒนา Python 2.x filterส่งคืนรายการแล้ว ในPython 3.xfilterถูกเปลี่ยนเพื่อส่งคืนตัววนซ้ำดังนั้นจึงต้องถูกแปลงเป็นlist(เพื่อให้เห็นว่าพิมพ์ออกมาได้ดี)

ตัวอย่างโค้ด Python 3 ตัวอย่างโค้ด
Python 2.x


4
สวัสดีเมื่อฉันเรียกใช้โค้ดด้านบนฉันได้รับ<filter object at 0x1057acda0>ว่าฉันทำอะไรผิด?

1
ตามเอกสาร python (python 2.7.12): docs.python.org/2/library/functions.html#filter filter จะส่งคืนรายการที่ไม่ใช่วัตถุ นอกจากนี้คุณยังสามารถตรวจสอบรหัสนั้น: repl.it/X3G/5786 (เพียงแค่กดเรียกใช้)
Mercury

1
ขอขอบคุณ. ฉันใช้ Python 3.5.2 บน Mac ฉันลองลิงค์ของคุณแล้ว แน่นอนว่ามันใช้งานได้ แต่ไม่แน่ใจว่าทำไมฉันถึงได้รับข้อความนั้น ฉันยังลบstrตั้งแต่filterส่งคืนรายการอยู่ดี แต่ก็ไม่มีประโยชน์ ...

4
@joshua ตอนนี้คุณคงคิดออกแล้ว แต่ลองprint(list(newlist))หรือprint([i for i in newlist])
James Draper

1
นี่เป็นเรื่องยากอย่างน่าขัน นี่คือสาเหตุที่ R เหนือกว่า เพียง grep (รูปแบบ vector_of_names)
MadmanLee

1

ในการดำเนินการดังกล่าวโดยไม่ต้องรวบรวม Regex ก่อนให้ใช้lambdaฟังก์ชัน - ตัวอย่างเช่น:

from re import match

values = ['123', '234', 'foobar']
filtered_values = list(filter(lambda v: match('^\d+$', v), values))

print(filtered_values)

ผลตอบแทน:

['123', '234']

filter()เพียงแค่รับcallableเป็นอาร์กิวเมนต์แรกและส่งกลับรายการที่เรียกได้ว่าส่งคืนค่า 'จริง'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.