【问题标题】:combine yield with if/else loop in python在python中将yield与if / else循环结合起来
【发布时间】:2019-03-19 10:20:21
【问题描述】:

我想在法语单词列表中加入两个用星号 (*) 分隔的单词。加入这些词后,我想检查这个词是否存在于法语词典中。如果是,则连接的单词应保留在列表中,否则应附加到另一个列表中。我在我的代码中使用了 yield (我是这个函数的新手),但是我的嵌套 if/else 循环有问题。任何人都可以帮助我实现我的目标吗?我不成功的代码如下:

words = ['Bien', '*', 'venue', 'pour', 'les','engage', '*', 'ment','trop', 'de', 'YIELD', 'peut','être','contre', '*', 'productif' ]

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

l=[ ]

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



print(list(join_asterisk(words)))

【问题讨论】:

  • 也许是Fr-dictionary.txt 的样本和所需的输出?
  • 显示预期结果
  • 首先,我建议摆脱索引并使用for w1, w2, w3 in zip(words, words[1:], words[2:]) 之类的东西只能访问连续的三个单词。它将帮助您思考并使您的代码更易于阅读。

标签: python if-statement while-loop yield


【解决方案1】:

生成器非常适合此用例,您可以将生成器视为一个函数,它会一个一个地为您提供生成的值,而不是一次性提供所有的值(就像 return 一样)。换句话说,你可以把它看成一个不在内存中的列表,一个只有在被请求时才会得到下一个元素的列表。另请注意,生成器只是构建iterators 的一种方式。

在您的情况下,这意味着您不必构建列表 l 来跟踪正确的单词,因为生成器 join_asterisk 将为您生成正确的单词。您需要做的是迭代此生成器将产生的所有值。这正是list(generator) 要做的事情,它将通过迭代生成器的所有值来构建一个列表。

最后的代码是这样的:

# That look better to me (just in case you change it later)
word_separator = '*'

words = ['Bien', word_separator, 'venue', 'pour', 'les','engage', word_separator, 'ment','trop', 'de', 'YIELD', 'peut', word_separator, "tard"]

# Fake dictionary
dic = {"Bienvenue", "pour", "les", "engagement", "trop", "de", "peut", "peut-être"}

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 = []
for word, is_correct in join_asterisk(words):
  if is_correct:
    correct_words.append(word)
  else:
    incorrect_words.append(word)

print(correct_words)
print(incorrect_words)

这个输出

['Bienvenue', 'pour', 'les', 'engagement', 'trop', 'de']
['peuttard']

还请注意,您可以使用列表推导而不是使用 for 循环来填充两个列表:

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]

【讨论】:

  • 太棒了!但是最好将不在字典中的串联单词分开。因为这个程序是连接由换行符分隔的单词,我想稍后检查哪些单词是由程序连接但不应该连接的。有可能这样做吗?如果是这样,你能更新代码吗?谢谢!!
  • 有可能,我认为最好的技术是拥有一个生成元组而不仅仅是单词的生成器。这些元组将包含单词和一个布尔值,用于指示给定单词是否在字典中。我可以更新我的答案:)
  • 好的!伟大的!我现在明白你做了什么!非常聪明!!我希望我能像你一样精通python!非常感谢!
【解决方案2】:

看起来像这样的线条:

        i+=1
        l.append(ary[i] + ary[i+2])

缩进不够,因此不涉及else。这意味着每对带有 * 的单词都将被附加到 l 而不仅仅是不在 dic 中的单词对。

【讨论】:

  • 我已经修复了缩进,但程序仍然无法运行
【解决方案3】:

你不是在寻找这样的东西吗:

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

“else”块遵循相同的规则。

例如,在 'if'、'elif'、'else' 或 'while' 子句的同一行中添加一个表达式是可行的,但如果您想要的不仅仅是与子句关联的表达式,则必须使用缩进或分隔带有';'的表达式像这样:

while 1:print(9,end='');print(8)

【讨论】:

    猜你喜欢
    • 2021-09-18
    • 2021-12-22
    • 2015-08-12
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2018-03-27
    • 2019-06-13
    相关资源
    最近更新 更多