[英]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.