Python覆盖了我的原始列表
我正在尝试写一段代码,假设我有四个数字的组合,其中有三个数字的位置是正确的。我想要遍历所有可能的数字,并生成所有可能的组合。简单来说,如果我有一个组合是[1,2,3,4],而我知道其中三个数字的位置是对的,我想生成像这样的组合: [2,2,3,4]、[3,2,3,4]、[4,2,3,4]、[5,2,3,4]、[6,2,3,4]、[1,1,3,4]、[1,3,3,4]、[1,4,3,4]、[1,5,3,4]、[1,6,3,4]、[1,2,1,4],等等...
我有一段代码可以生成所有可能的组合,结果是[6,6,6,6]。
def create_guess_list(guess):
guess_list = []
for i in range(0,4):
for j in range(1,7):
temp = guess
if j != temp[i]:
temp[i] = j
guess_list.append(temp)
return guess_list
我在想,每次我创建一个新组合的时候,尽管我把它放在一个临时列表里,Python是不是在覆盖它?我该怎么做才能避免这种情况,而不需要每次都创建一个空列表并逐步添加? (或者这就是唯一的方法吗?)
4 个回答
在编程中,有时候我们会遇到一些问题,特别是在使用特定的工具或库时。比如,有人可能在使用某个库的时候,发现它的某些功能没有按照预期工作。这种情况可能会让人感到困惑,因为我们可能不知道问题出在哪里。
通常,解决这类问题的第一步是仔细检查代码,确保没有拼写错误或其他简单的错误。接下来,可以查看库的文档,看看是否有相关的使用说明或示例代码,这样可以帮助我们更好地理解如何正确使用这些功能。
如果还是找不到问题所在,可以考虑在网上搜索一下,看看其他人是否遇到过类似的问题,或者在相关的论坛上提问,寻求帮助。记住,编程是一个不断学习和解决问题的过程,不要害怕寻求帮助!
from itertools import combinations, product
ALPHABET = [1, 2, 3, 4, 5, 6]
SAME = {a:[a] for a in ALPHABET}
DIFF = {a:[x for x in ALPHABET if x != a] for a in ALPHABET}
def all_possible_solutions(guess, num_right):
# how many items need to be substituted?
width = len(guess)
num_wrong = width - num_right
# which items should be substituted?
for replace_at in combinations(range(width), num_wrong):
# figure out new basis
basis = [
DIFF[g] if index in replace_at else SAME[g]
for index,g in enumerate(guess)
]
# return combinations from new basis
for combo in product(*basis):
yield combo
temp = guess
这行代码是把 guess
里的内容赋值给一个叫 temp
的变量(这两个变量其实指向的是同一个对象)。
如果你想要创建一个独立的副本,就应该从 guess
创建一个新的列表,像这样:
temp = list(guess) # or temp = guess[:]
你可以使用 itertools.product
来生成所有可能的组合,然后筛选出那些匹配数字不够的组合:
import itertools
def guess_list (guess, correct):
for combination in itertools.product(range(1, 7), repeat=4):
if sum(c == g for c, g in zip(combination, guess)) == correct:
yield combination
>>> list(guess_list([1, 2, 3, 4], 3))
[(1, 1, 3, 4), (1, 2, 1, 4), (1, 2, 2, 4), (1, 2, 3, 1), (1, 2, 3, 2), (1, 2, 3, 3), (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 3, 6), (1, 2, 4, 4), (1, 2, 5, 4), (1, 2, 6, 4), (1, 3, 3, 4), (1, 4, 3, 4), (1, 5, 3, 4), (1, 6, 3, 4), (2, 2, 3, 4), (3, 2, 3, 4), (4, 2, 3, 4), (5, 2, 3, 4), (6, 2, 3, 4)]
至于你的解决方案,问题在于你修改了原来的猜测。在 temp = guess
这行代码中,你只是复制了对猜测列表的引用。所以 guess
和 temp
这两个变量实际上指向的是同一个列表对象。然后,当你执行 temp[i] = j
时,你是在改变这个列表对象中的一个元素,而这个列表是两个变量都在引用的。因此,你实际上是在改变原来的猜测(这会导致后面对 guess
的检查都不正确)。同样的原因,你还一直在把同一个对象添加到 guess_list
列表中。要解决这个问题,你需要创建一个 guess
列表的副本;你可以用 temp = guess[:]
来做到这一点。
复制一个列表最简单的方法就是用完整的切片。把这一行
temp = guess
改成这样
temp = guess[:]
如果你不复制这个列表,不管是用切片还是其他方法,那么你就会有两个变量指向同一个列表。