繁体   English   中英

从 Python 中的列表中删除单词的问题

[英]Issues removing words from a list in Python

我正在构建一个 Wordle 求解器。 基本上从列表中删除单词,如果它们没有特定字符,或者没有它们在特定位置。 我还不关心最优选择的统计数据。

当我运行下面的代码时(我认为所有相关部分都包括在内),我的 output 很明显它找到了一个匹配 position 的字母到“今日词汇”。 但是在下一次迭代中,它会选择一个没有那个字母的单词,而此时它应该只从剩余的单词中选择 select。

单词实际上没有被删除吗? 还是有什么东西隐藏了我找不到的 scope? 我重写了整个部分,发生了完全相同的问题。

#Some imports and reading the word list here. 

def word_compare(word_of_the_day, choice_word):
    results = []
    index = 0
    letters[:] = choice_word
    for letter in letters:
        if letter is word_of_the_day[index]:
            results.append((letter, 2, index))
        elif letter in word_of_the_day:
            results.append((letter, 1, index))
        else:
            results.append((letter, 0, index))
        index += 1
    print("\nIteration %s\nWord of the Day: %s,\nChoice Word: %s,\nResults: %s" % (
        iteration, word_of_the_day, choice_word, results))
    return results


def remove_wrong_words():
    for item in results:
        if item[1] == 0:
            for word in words:
                if item[0] in word:
                    words.remove(word)
    for item in results:
        if item[1] == 2:
            for word in words:
                if word[item[2]] != item[0]:
                    words.remove(word)
    print("Words Remaining: %s" % len(words))
    return words


words, letters = prep([])
# choice_word = best_word_choice()
choice_word = "crane"
iteration = 1
word_of_the_day = random.choice(words)

while True:
    if choice_word == word_of_the_day:
        break
    else:
        words.remove(choice_word)
        results = word_compare(word_of_the_day, choice_word)
        words = remove_wrong_words()
        if len(words) < 10:
            print(words)
        choice_word = random.choice(words)
        iteration += 1

Output 我得到:

Iteration 1
Word of the Day: stake,
Choice Word: crane,
Results: [('c', 0, 0), ('r', 0, 1), ('a', 2, 2), ('n', 0, 3), ('e', 2, 4)]
Words Remaining: 386

Iteration 2
Word of the Day: stake,
Choice Word: lease,
Results: [('l', 0, 0), ('e', 1, 1), ('a', 2, 2), ('s', 1, 3), ('e', 2, 4)]
Words Remaining: 112

Iteration 3
Word of the Day: stake,
Choice Word: paste,
Results: [('p', 0, 0), ('a', 1, 1), ('s', 1, 2), ('t', 1, 3), ('e', 2, 4)]
Words Remaining: 81

Iteration 4
Word of the Day: stake,
Choice Word: spite,

... 这会持续一段时间,直到解决。 在这个 output 中,'a' 在第二次迭代中被发现位于正确的位置(元组中值为 2)。 这应该从列表中删除第三个字符不是“a”的所有单词。 相反,'paste' 和 'spite' 是从同一个列表中选择用于以后的迭代,而不是被删除。

您的问题与在迭代时从列表中删除项目有关。 这通常会导致跳过后面的值,因为列表迭代是由索引在幕后处理的。

具体来说,问题就在这里(也可能在另一个循环中):

for word in words:
    if item[0] in word:
        words.remove(word)

如果words列表中的第一个单词的if条件为真,则不会检查第二个单词。 那是因为当for循环向列表迭代器询问下一个值时,它将产生列表的第二个值,因为它现在是这样的,这将是原始列表中的第三个值(因为第一个已经不存在了) .

有几种方法可以避免此问题。

一种方法是迭代您要修改的列表的副本。 这意味着迭代器永远不会跳过任何东西,因为复制的列表在您 go 时没有从中删除任何内容(只有原始列表正在更改)。 制作副本的一种常见方法是使用切片:

for word in words[:]:       # iterate on a copy of the list
    if item[0] in word:
        words.remove(word)  # modify the original list here

另一种选择是构建一个包含原始列表中有效值的新列表,而不是删除无效值。 列表推导式通常就足够了:

words = [word for word in words if item[0] not in word]

这在您的示例中可能会稍微复杂一些,因为您使用的是全局变量。 您可能需要更改该设计(例如,接受一个列表作为参数并返回新版本),或者添加global words语句以让函数的代码重新绑定全局变量(而不是就地修改它)。

我认为您的问题之一是以下行: if letter is word_of_the_day[index]: 这应该是== not is因为后者检查被比较的两个对象是否具有相同的 memory 地址(即id() ),而不是它们是否具有相同的值。 因此, results永远不会在 position 1 中返回值为 2 的元组,因此这意味着remove_wrong_words中的第二个 for 循环也不会执行任何操作。 可能还有更多的事情要做,但我想在进一步挖掘之前运行一个具体的例子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM