嵌套列表中的SUM编号

时间:2016-02-24 08:59:17

标签: python-3.x nested-loops

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

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]

1 个答案:

答案 0 :(得分:3)

问题在于

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]时,您实际上正在修改subtabletable3[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)])

请注意,通过使用summap应用于每对,也可以实现列表推导中的这种成对添加:

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)]

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