SUM 嵌套列表中的数字

SUM numbers in a nested list

目前我正在尝试对两个嵌套循环中的数字求和。我非常接近,但由于某种原因,数字没有正确添加。

def addTables(table1,table2):
counter = 0
index = 0
table3 = [[None] * len(table1[0])] * len(table1)
print(table3)
for row in table1:
    for i in table1[0]:
        table3[counter][index] = table1[counter][index] + table2[counter][index]
        index = index +1
    index = 0
    counter = counter + 1
    print (table3)

我的值是 table1 = [[1,2,3],[4,5,6]]table2 = [[1,2,3],[4,5,6]]。 由于某种原因,它正在打印

[[None, None, None], [None, None, None]]
[[2, 4, 6], [2, 4, 6]]
[[8, 10, 12], [8, 10, 12]]

但我想要打印出来

[[None, None, None], [None, None, None]]
[[2, 4, 6], [None, None, None]]
[[2, 4, 6], [8, 10, 12]]

我认为这行是错误的,但我不知道如何修正它。

table3[counter][index] = table1[counter][index] + table2[counter]

问题出在

table3 = [[None] * len(table1[0])] * len(table1)

相乘一个列表实际上复制了对其项目的引用;它不会重复列表中的项目。要查看会发生什么,请像这样查看您的代码:

subtable = [None] * len(table1[0])]
# subtable = [None, None, None]
table3 = [subtable] * len(table1)
# table3 = [subtable, subtable]

因此,table3[0]table3[1]实际上是同一个列表。所以当你设置table3[0][0]时,你实际上是在修改subtable,也就是table3[0]table3[1]!

这个效果大家可以自己看看:

>>> table3 = [[None] * 3] * 2
>>> table3
[[None, None, None], [None, None, None]]
>>> table3[0][1] = 5
>>> table3
[[None, 5, None], [None, 5, None]]

您可以通过使用 list comprehensions 构造 table3:

来解决这个问题
>>> table3 = [[None for x in table1[0]] for y in table1]
>>> table3
[[None, None, None], [None, None, None]]
>>> table3[0][1] = 5
>>> table3
[[None, 5, None], [None, None, None]]

或者,对内部列表使用列表乘法也可以。 (这是因为对 None 的引用被替换,而对子列表的引用被原地修改):

>>> table3 = [[None] * len(table1[0]) for y in table1]
>>> table3
[[None, None, None], [None, None, None]]
>>> table3[0][1] = 5
>>> table3
[[None, 5, None], [None, None, None]]

虽然这种微妙之处可能令人困惑。使用嵌套列表理解更明确。

但就个人而言,我一开始不会像那样提前构建列表。相反,我会建议从一个空列表开始,并在你进行时附加到它

table3 = []
for row in table1:
    sumrow = []
    index = 0
    for i in table1[0]:
        sumrow.append(table1[counter][index] + table2[counter][index])
        index += 1
    table3.append(sumrow)
    counter += 1

并且,在此基础上,直接迭代列表而不是迭代它们的索引通常更清晰。您可以使用 zip 遍历两个大小相同的列表,如下所示:

for row1, row2 in zip(table1, table2):
    sumrow = []
    for item1, item2 in zip(row1, row2):
        sumrow.append(item1 + item2)
    table3.append(sumrow)

一旦到达那里,我们就可以将 sumrow 表示为列表理解:

for row1, row2 in zip(table1, table2):
    table3.append([item1 + item2 for item1, item2 in zip(row1, row2)])

请注意,列表理解中的这种成对添加也可以通过应用 sum to every pair using map:

来实现
for row1, row2 in zip(table1, table2):
    table3.append(list(map(sum, zip(row1, row2))))

然后我们还可以用列表理解替换外部 for 循环。

table3 = [list(map(sum, zip(row1, row2))) for row1, row2 in zip(table1, table2)]

可以通过对行使用列表解包来稍微改进:

table3 = [list(map(sum, zip(*rows))) for rows in zip(table1, table2)]

如果这实际上是最好/最易读的方法,我有点矛盾,所以也许我应该在几个版本前停止。但是,嘿,我们到了 ;)