从 Python 中的列表中删除单词时出现问题
Issues removing words from a list in Python
我正在构建一个 Wordle 求解器。基本上从列表中删除单词,如果它们没有特定字符,或者没有它们在特定位置。我还不关心最优选择的统计数据。
当我 运行 下面的代码(我认为所有相关部分都包括在内)时,我的输出很清楚它找到了一个与 'word of the day' 匹配的字母位置。但是在下一次迭代中,它会选择一个没有那个字母的单词,而它应该只从剩余的单词中选择 select。
字真的没有被删除吗?还是有什么东西遮住了我找不到的范围?
我重写了整个部分,发生了完全相同的问题。
#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
我得到的输出:
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,
...这会持续一段时间直到解决。在此输出中,发现 'a' 在第二次迭代中位于正确的位置(元组中的值 2)。这应该从列表中删除所有没有 'a' 作为第三个字符的单词。相反,'paste' 和 'spite' 是从同一个列表中选择用于以后的迭代,而不是被删除。
我认为您的问题之一是以下行:if letter is word_of_the_day[index]:
。这应该是 ==
而不是 is
,因为后者检查的是被比较的两个对象是否具有相同的内存地址(即 id()
),而不是它们是否具有相同的值。因此,results
永远不会 return 位置 1 值为 2 的元组,所以这意味着 remove_wrong_words
中的第二个 for 循环也不会做任何事情。可能还有更多的事情要发生,但我想要一个具体的例子 运行 在进一步挖掘之前。
您的问题与在迭代时从列表中删除项目有关。这通常会导致跳过后面的值,因为列表迭代是由索引在幕后处理的。
具体来说,问题出在这里(也可能在另一个循环中):
for word in words:
if item[0] in word:
words.remove(word)
如果 if
条件对于 words
列表中的第一个单词为真,则不会检查第二个单词。那是因为当 for
循环向列表迭代器询问下一个值时,它将产生列表的第二个值 ,因为它现在是 ,这将是原始列表中的第三个值(因为第一个已经消失)。
有几种方法可以避免此问题。
一种方法是迭代您要修改的列表的副本。这意味着迭代器永远不会跳过任何内容,因为复制的列表在您进行时没有从中删除任何内容(只有原始列表正在更改)。制作副本的常用方法是使用切片:
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]
这在您的示例中可能会稍微复杂一些,因为您使用的是全局变量。您可能需要更改该设计(例如接受列表作为参数和 return 新版本),或者添加 global words
语句让函数的代码重新绑定全局变量(而不是修改它到位)。
我正在构建一个 Wordle 求解器。基本上从列表中删除单词,如果它们没有特定字符,或者没有它们在特定位置。我还不关心最优选择的统计数据。
当我 运行 下面的代码(我认为所有相关部分都包括在内)时,我的输出很清楚它找到了一个与 'word of the day' 匹配的字母位置。但是在下一次迭代中,它会选择一个没有那个字母的单词,而它应该只从剩余的单词中选择 select。
字真的没有被删除吗?还是有什么东西遮住了我找不到的范围? 我重写了整个部分,发生了完全相同的问题。
#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
我得到的输出:
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,
...这会持续一段时间直到解决。在此输出中,发现 'a' 在第二次迭代中位于正确的位置(元组中的值 2)。这应该从列表中删除所有没有 'a' 作为第三个字符的单词。相反,'paste' 和 'spite' 是从同一个列表中选择用于以后的迭代,而不是被删除。
我认为您的问题之一是以下行:if letter is word_of_the_day[index]:
。这应该是 ==
而不是 is
,因为后者检查的是被比较的两个对象是否具有相同的内存地址(即 id()
),而不是它们是否具有相同的值。因此,results
永远不会 return 位置 1 值为 2 的元组,所以这意味着 remove_wrong_words
中的第二个 for 循环也不会做任何事情。可能还有更多的事情要发生,但我想要一个具体的例子 运行 在进一步挖掘之前。
您的问题与在迭代时从列表中删除项目有关。这通常会导致跳过后面的值,因为列表迭代是由索引在幕后处理的。
具体来说,问题出在这里(也可能在另一个循环中):
for word in words:
if item[0] in word:
words.remove(word)
如果 if
条件对于 words
列表中的第一个单词为真,则不会检查第二个单词。那是因为当 for
循环向列表迭代器询问下一个值时,它将产生列表的第二个值 ,因为它现在是 ,这将是原始列表中的第三个值(因为第一个已经消失)。
有几种方法可以避免此问题。
一种方法是迭代您要修改的列表的副本。这意味着迭代器永远不会跳过任何内容,因为复制的列表在您进行时没有从中删除任何内容(只有原始列表正在更改)。制作副本的常用方法是使用切片:
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]
这在您的示例中可能会稍微复杂一些,因为您使用的是全局变量。您可能需要更改该设计(例如接受列表作为参数和 return 新版本),或者添加 global words
语句让函数的代码重新绑定全局变量(而不是修改它到位)。