我正在尝试创建一个字典(sums),其键是列表的总和,而值是列表本身。该列表具有不同数量的元素,但名称相同。每次更改列表的元素并将此更改后的列表(相同名称)分配给其他键时,先前分配给键的值也会更改。
在寻找合适的答案时,我从这里(https://stackoverflow.com/a/52806573/7198441)得知这可能是因为Python也引用了列表(如果在此处出错,请更正我)。现在,我想知道,是否有一种方法可以将具有相同名称但在迭代的不同阶段具有不同元素的列表分配给同一词典的不同键。
l = [1, 2, 3, 4, 5]
sums = {}
while len(l) :
l_sum = sum(l)
sums[l_sum] = l
print(sums)
print()
l.pop()
实际结果:
{15: [1, 2, 3, 4, 5]}
{15: [1, 2, 3, 4], 10: [1, 2, 3, 4]}
{15: [1, 2, 3], 10: [1, 2, 3], 6: [1, 2, 3]}
{15: [1, 2], 10: [1, 2], 6: [1, 2], 3: [1, 2]}
{15: [1], 10: [1], 6: [1], 3: [1], 1: [1]}
预期:
{15: [1, 2, 3, 4, 5]}
{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4]}
{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3]}
{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2]}
{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2], 1: [1]}
答案 0 :(得分:1)
您正在对列表对象的一个实例执行所有操作。这就是为什么在最终结果中,所有值都得到相同的列表的原因。可以使用字典理解或itertools.accumulate
来获取列表项的累加和,然后使用zip来创建所需的字典,而不是循环。
In [13]: {sum(l[:i + 1]): l[:i + 1] for i in range(len(l))}
Out[13]: {1: [1], 3: [1, 2], 6: [1, 2, 3], 10: [1, 2, 3, 4], 15: [1, 2, 3, 4, 5]}
或(较少Pythonic):
In [7]: dict(zip(accumulate(l), [l[:i + 1] for i in range(len(l))]))
Out[7]: {1: [1], 3: [1, 2], 6: [1, 2, 3], 10: [1, 2, 3, 4], 15: [1, 2, 3, 4, 5]}
答案 1 :(得分:1)
问题在于,当您执行sums[l_sum] = l
时,您正在使用对原始列表的引用。因此,在while循环的任何步骤中进行的所有更改都会影响使用此列表的所有其他位置。这就是为什么您在每张纸上看到列表都会更改的原因。
简单的解决方案是使用sums[l_sum] = l[:]
复制列表。
while len(l) :
l_sum = sum(l)
sums[l_sum] = l[:] # <--- changed here from l to l[:]
print(sums)
print()
l.pop()
# {15: [1, 2, 3, 4, 5]}
# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4]}
# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3]}
# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2]}
# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2], 1: [1]}