我的for-loop与yield相结合的问题

问题描述 投票:1回答:2

我有一个程序连接用星号分隔的单词。程序删除星号并将单词的第一部分(星号前面的部分)与第二部分(星号后面的部分)连接起来。除了一个主要问题外,它运行良好:第二部分(在星号之后)仍在输出中。例如,程序连接['presi','*','dent'],但'凹'仍然在输出中。我没弄明白代码的问题在哪里。代码如下:

from collections import defaultdict
import nltk
from nltk.tokenize import word_tokenize
import re
import os
import sys
from pathlib import Path


def main():
    while True:
        try:
            file_to_open =Path(input("\nPlease, insert your file path: "))

            with open(file_to_open) as f:
                words = word_tokenize(f.read().lower())
                break
        except FileNotFoundError:
            print("\nFile not found. Better try again")
        except IsADirectoryError:
            print("\nIncorrect Directory path.Try again")

    word_separator = '*'

    with open ('Fr-dictionary2.txt') as fr:
            dic = word_tokenize(fr.read().lower())

    def join_asterisk(ary):

        for w1, w2, w3 in zip(words, words[1:], words[2:]):
            if w2 == word_separator:
                word = w1 + w3
                yield (word, word in dic)
            elif w1 != word_separator and w1 in dic:
                yield (w1, True)


    correct_words = []
    incorrect_words = []
    correct_words = [w for w, correct in join_asterisk(words) if correct]
    incorrect_words = [w for w, correct in join_asterisk(words) if not correct]
    text=' '.join(correct_words)
    print(correct_words)
    print('\n\n', text)
    user2=input('\nWrite text to a file? Type "Y" for yes or "N" for no:')

    text_name=input("name your file.(Ex. 'my_first_file.txt'): ")
    out_file=open(text_name,"w")

    if user2 =='Y':
        out_file.write(text)
        out_file.close()
    else:
        print('ok')


main()

我想知道是否有人可以帮助我在这里发现错误?

输入示例:

共和国总统的承诺也是“铁路”社会领导人的承诺,他在聚集在爱丽舍的大东方民选官员面前说。

2017年7月1日,共和国总统Emmanuel Macron(右侧)与SNCF老板Guillaume Pepy一起在巴黎Montparnasse车站工作.GEOFFROY VAN DER HASSELT / AFP

在面对废弃的火车或废弃的服务时,有时会抓住SNCF用户的恼怒似乎也抓住了共和国总统。在大选之前,2月26日星期二在爱丽舍宫举行的大辩论中,埃马纽埃尔·马克龙对于法国国营铁路公司(SNCF)采取了非常严厉的措辞,该公司于2018年12月23日关闭了圣迪耶 - 埃皮纳尔线,在2018年4月访问孚日期间,国家元首承诺将保持运作。

我当前输出的示例是:

['les', 'engagements', 'du', 'président', 'dent', 'de', 'la', 'république', 'que', 'sont', 'aussi', 'ceux', 'des', 'dirigeants', 'de', 'la', 'société', 'ferroviaire'] 

我想要的输出示例是:

['les', 'engagements', 'du', 'président', 'de', 'la', 'république', 'sont', 'aussi', 'ceux', 'des', 'dirigeants', 'de', 'la', 'société', 'ferroviaire']
python for-loop nltk yield
2个回答
1
投票

两个额外的单词(我假设)都在你的字典中,因此在for循环的2次迭代后第二次产生,因为它们符合行中的w1时的情况:

            elif w1 != word_separator and w1 in dic:
                yield (w1, True)

重新设计你的join_asterisk函数似乎是最好的方法来做到这一点,因为任何修改这个函数以跳过这些的尝试都会令人难以置信的hacky。

以下是重新设计函数的方法,以便您可以跳过已被包含为单词的后半部分的单词,其中单词的后半部分由'*'分隔:

incorrect_words = []
def join_asterisk(array):
    ary = array + ['', '']
    i, size = 0, len(ary)
    while i < size - 2:
        if ary[i+1] == word_separator:
            if ary[i] + ary[i+2] in dic:
                yield ary[i] + ary[i+2]
            else:
                incorrect_words.append(ary[i] + ary[i+2])
            i+=2
        elif ary[i] in dic: 
            yield ary[i]
        i+=1

如果您希望它更接近原始功能,可将其修改为:

def join_asterisk(array):
    ary = array + ['', '']
    i, size = 0, len(ary)
    while i < size - 2:
        if ary[i+1] == word_separator:
            concat_word = ary[i] + ary[i+2]
            yield (concat_word, concat_word in dic)
            i+=2
        else: 
            yield (ary[i], ary[i] in dic)
        i+=1

0
投票

我认为join_asterisk的这种替代实现符合您的意图:

def join_asterisk(words, word_separator):
    if not words:
        return
    # Whether the previous word was a separator
    prev_sep = (words[0] == word_separator)
    # Next word to yield
    current = words[0] if not prev_sep else ''
    # Iterate words
    for word in words[1:]:
        # Skip separator
        if word == word_separator:
            prev_sep = True
        else:
            # If neither this or the previous were separators
            if not prev_sep:
                # Yield current word and clear
                yield current
                current = ''
            # Add word to current
            current += word
            prev_sep = False
    # Yield last word if list did not finish with a separator
    if not prev_sep:
        yield current

words = ['les', 'engagements', 'du', 'prési', '*', 'dent', 'de', 'la', 'républi', '*', 'que', 'sont', 'aussi', 'ceux', 'des', 'dirigeants', 'de', 'la', 'société', 'ferroviaire']
word_separator = '*'
print(list(join_asterisk(words, word_separator)))
# ['les', 'engagements', 'du', 'président', 'de', 'la', 'république', 'sont', 'aussi', 'ceux', 'des', 'dirigeants', 'de', 'la', 'société', 'ferroviaire']
© www.soinside.com 2019 - 2024. All rights reserved.