ค้นหาวลีคำนามก่อนและหลังตัวเลขในข้อความ

Aug 19 2020

เมื่อได้รับข้อความฉันต้องหาคำที่นำหน้าตัวเลขทั้งหมดไปจนถึงคำหยุดที่เป็นของรายการ 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: การตรวจสอบก่อนหน้านี้บางอย่างที่ฉันทำ:

  • การค้นหาตำแหน่งของรายการในรายการอื่นจากตัวเลขในรายการอื่น
  • การค้นหาดัชนีของรายการในรายการ
  • ค้นหาในรายการ

คำตอบ

MarioIshac Aug 19 2020 at 09:13

ฉันคิดสิ่งนี้:

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)

สำหรับรหัสเดิมของคุณฉันจะให้คำแนะนำสองสามข้อ:

  1. ปฏิบัติตามPEP 8 . i,wordตัวอย่างเช่นเพิ่มระยะห่างหลังจากจุลภาคใน
  2. preceding_words[::-1]นำการแสดงออกซ้ำซ้อน แม้ว่าสิ่งนี้จะประเมินเป็นแบบย้อนกลับpreceding_wordsเนื่องจากไม่ได้อยู่ในสถานที่การประเมินผลจึงไม่มีผลข้างเคียง นอกจากนี้คุณได้ทำการกลับรายการนี้enumerate(preceding_words[::-1])แล้ว