ค้นหาวลีคำนามก่อนและหลังตัวเลขในข้อความ
เมื่อได้รับข้อความฉันต้องหาคำที่นำหน้าตัวเลขทั้งหมดไปจนถึงคำหยุดที่เป็นของรายการ check_words (ประเภทของคำหยุด)
รหัสของฉัน:
check_words = ['the', 'a', 'with','to']
mystring = 'the code to find the beautiful words 78 that i have to nicely check 45 with the snippet'
list_of_words = mystring.split()
ในข้อความนั้นฉันจะตรวจสอบก่อน'78'
และ'45'
และจะย้อนกลับไปจนถึงจุดที่ฉันพบคำใด ๆ ใน check_words (แต่ไม่เกิน 8 คำ)
รหัสสำหรับการทำเช่นนั้นอาจเป็น:
preceding_chunks = []
for i,word in enumerate(list_of_words):
if any(char.isdigit() for char in word):
# 8 precedent words (taking into account that I can not slice with 8 back at the beginning)
preceding_words = list_of_words[max(0,i-8):i]
preceding_words[::-1]
# I check from the end of the list towards the start
for j,sub_word in enumerate(preceding_words[::-1]):
if sub_word in check_words:
# printing out j for checking
myposition = j
print(j)
real_preceding_chunk = preceding_words[len(preceding_words)-j:]
print(real_preceding_chunk)
preceding_chunks.append(real_preceding_chunk)
break
รหัสนี้ใช้งานได้ โดยพื้นฐานแล้วฉันตรวจทุกคำท่า แต่ฉันมีความประทับใจ (บางทีฉันคิดผิด) ว่ามันสามารถทำได้ด้วยสองสมุทรและด้วยเหตุนี้โดยไม่ต้องวนซ้ำ ความคิดใด ๆ ?
หมายเหตุ: คำถามนี้เกี่ยวกับการปรับปรุงความสามารถในการอ่านโค้ดพยายามกำจัดลูปเพื่อทำให้โค้ดเร็วขึ้นและพยายามทำให้โค้ดดีขึ้นซึ่งเป็นส่วนหนึ่งของ Zen of Python
หมายเหตุ 2: การตรวจสอบก่อนหน้านี้บางอย่างที่ฉันทำ:
- การค้นหาตำแหน่งของรายการในรายการอื่นจากตัวเลขในรายการอื่น
- การค้นหาดัชนีของรายการในรายการ
- ค้นหาในรายการ
คำตอบ
ฉันคิดสิ่งนี้:
import itertools
import re
chunks = (grouped_chunk.split() for grouped_chunk in re.split("\\s+\\d+\\s+", mystring))
preceding_chunks = []
for reversed_chunk in map(reversed, chunks):
preceding_chunk = list(itertools.takewhile(lambda word: word not in check_words, reversed_chunk))[::-1]
preceding_chunks.append(preceding_chunk)
เรานำitertools.takewhile
ไปใช้กับสิ่งreversed_chunk
ที่ให้เราก่อนหน้าในลำดับที่กลับกัน จากนั้นเราจะได้รับการสั่งการได้อย่างถูกต้องโดยการกลับในตอนท้ายด้วยpreceding_chunk
[::-1]
regex แยกmystring
ตามตัวเลข (ค่า Escape \d+
) ค่า Escape โดยรอบ\s+
แสดงถึงช่องว่างรอบ ๆ จำนวน สิ่งนี้ทำให้รหัสนี้มีพฤติกรรมที่แตกต่างจากของคุณหากตัวเลขและตัวอักษรผสมกันในคำเดียวกัน (ตัวอย่างเช่นa1
)
สำหรับรหัสเดิมของคุณฉันจะให้คำแนะนำสองสามข้อ:
- ปฏิบัติตามPEP 8 .
i,word
ตัวอย่างเช่นเพิ่มระยะห่างหลังจากจุลภาคใน preceding_words[::-1]
นำการแสดงออกซ้ำซ้อน แม้ว่าสิ่งนี้จะประเมินเป็นแบบย้อนกลับpreceding_words
เนื่องจากไม่ได้อยู่ในสถานที่การประเมินผลจึงไม่มีผลข้างเคียง นอกจากนี้คุณได้ทำการกลับรายการนี้enumerate(preceding_words[::-1])
แล้ว