Python覆盖了我的原始列表

0 投票
4 回答
1982 浏览
提问于 2025-04-18 05:11

我正在尝试写一段代码,假设我有四个数字的组合,其中有三个数字的位置是正确的。我想要遍历所有可能的数字,并生成所有可能的组合。简单来说,如果我有一个组合是[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 个回答

0

在编程中,有时候我们会遇到一些问题,特别是在使用特定的工具或库时。比如,有人可能在使用某个库的时候,发现它的某些功能没有按照预期工作。这种情况可能会让人感到困惑,因为我们可能不知道问题出在哪里。

通常,解决这类问题的第一步是仔细检查代码,确保没有拼写错误或其他简单的错误。接下来,可以查看库的文档,看看是否有相关的使用说明或示例代码,这样可以帮助我们更好地理解如何正确使用这些功能。

如果还是找不到问题所在,可以考虑在网上搜索一下,看看其他人是否遇到过类似的问题,或者在相关的论坛上提问,寻求帮助。记住,编程是一个不断学习和解决问题的过程,不要害怕寻求帮助!

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
1

temp = guess 这行代码是把 guess 里的内容赋值给一个叫 temp 的变量(这两个变量其实指向的是同一个对象)。

如果你想要创建一个独立的副本,就应该从 guess 创建一个新的列表,像这样:

temp = list(guess)  # or temp = guess[:]
2

你可以使用 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 这行代码中,你只是复制了对猜测列表的引用。所以 guesstemp 这两个变量实际上指向的是同一个列表对象。然后,当你执行 temp[i] = j 时,你是在改变这个列表对象中的一个元素,而这个列表是两个变量都在引用的。因此,你实际上是在改变原来的猜测(这会导致后面对 guess 的检查都不正确)。同样的原因,你还一直在把同一个对象添加到 guess_list 列表中。要解决这个问题,你需要创建一个 guess 列表的副本;你可以用 temp = guess[:] 来做到这一点。

2

复制一个列表最简单的方法就是用完整的切片。把这一行

temp = guess

改成这样

temp = guess[:]

如果你不复制这个列表,不管是用切片还是其他方法,那么你就会有两个变量指向同一个列表。

撰写回答