簡體   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