无法将元素添加到嵌套列表
Failed to add element to nested lists
背景(非题主):
我正在尝试解决从列表中所有长度为 2 的路径的列表(下面代码中的p2
)生成所有长度为 3 的路径的问题。
为此,我想存储所有索引对 (i,j)
p2[i][1]==p2[j][0] and `p2[i][2]==p2[j][1]
(长度为 2 的路径由 3 个顶点的序列定义)
问题:
我尝试将索引存储在二维列表中,其条目最初是空列表,附加了新遇到的索引,但生成的是一个二维列表,其条目是包含所有索引的列表。
有人可以解释幕后实际发生的事情以及如何正确地将索引添加到最里面的列表吗?
# -*- coding: utf-8 -*-
"""
Created on Sun May 29 10:10:40 2022
@author: Manfred Weis
"""
# generare all unsorted 3-tuples
from itertools import permutations
n=4
p2 = list(permutations(range(n),3))
print('p2:')
print(p2)
print()
N = len(p2)
Rows = [[[]]*n]*n # create 3D list
Cols = [[[]]*n]*n # create 3D list
for i in range(N):
print(str(i)+': Rows['+str(p2[i][1])+']['+str(p2[i][2])+']')
print(str(i)+': Cols['+str(p2[i][0])+']['+str(p2[i][1])+']')
(Rows[p2[i][1]][p2[i][2]]).append(i) # add to the most nested list
(Cols[p2[i][0]][p2[i][1]]).append(i) # add to the most nested list
for i in range(n):
for j in range(n):
print(str(i)+','+str(j)+':')
print(str(Rows[i][j]))
print(str(Cols[i][j]))
print()
您在初始化 Rows 和 Cols 3D 列表时遇到浅拷贝问题。您需要像这样初始化它们,而不是使用乘法:
for k in range(n):
Rows.append([])
Cols.append([])
for l in range(n):
Rows[k].append([])
Cols[k].append([])
为了初始化列表的 3D 列表而进行乘法的问题是,里面的所有 n 个列表都指向同一个列表,所以当你附加到其中一个时,你附加到所有的列表,因为它们在技术上只是彼此的浅拷贝。因此,当您在最后打印它们时,所有列表都会添加所有数字,因为它们都指向内存中的同一个位置。通过使用上述方法初始化 3D 列表,您将在内存中的不同位置创建单独的列表,并将它们中的每一个插入到 Rows 和 Cols 3D 列表中。
看看当您执行以下操作时会发生什么:
x = [[]]*2
x[0].append(5)
输出:
[[5], [5]]
但如果您执行以下操作,问题就解决了:
x = [[],[]]
x[0].append(5)
输出:
[[5], []]
这里有一些其他人的解释比我的更好:
List of lists changes reflected across sublists unexpectedly
编辑:
这里有一个更好的 pythonic 方式来初始化行和列:
Rows = [[ [] for j in range(n)] for i in range(n)]
Cols = [[ [] for j in range(n)] for i in range(n)]
背景(非题主):
我正在尝试解决从列表中所有长度为 2 的路径的列表(下面代码中的p2
)生成所有长度为 3 的路径的问题。
为此,我想存储所有索引对 (i,j)
p2[i][1]==p2[j][0] and `p2[i][2]==p2[j][1]
(长度为 2 的路径由 3 个顶点的序列定义)
问题:
我尝试将索引存储在二维列表中,其条目最初是空列表,附加了新遇到的索引,但生成的是一个二维列表,其条目是包含所有索引的列表。
有人可以解释幕后实际发生的事情以及如何正确地将索引添加到最里面的列表吗?
# -*- coding: utf-8 -*-
"""
Created on Sun May 29 10:10:40 2022
@author: Manfred Weis
"""
# generare all unsorted 3-tuples
from itertools import permutations
n=4
p2 = list(permutations(range(n),3))
print('p2:')
print(p2)
print()
N = len(p2)
Rows = [[[]]*n]*n # create 3D list
Cols = [[[]]*n]*n # create 3D list
for i in range(N):
print(str(i)+': Rows['+str(p2[i][1])+']['+str(p2[i][2])+']')
print(str(i)+': Cols['+str(p2[i][0])+']['+str(p2[i][1])+']')
(Rows[p2[i][1]][p2[i][2]]).append(i) # add to the most nested list
(Cols[p2[i][0]][p2[i][1]]).append(i) # add to the most nested list
for i in range(n):
for j in range(n):
print(str(i)+','+str(j)+':')
print(str(Rows[i][j]))
print(str(Cols[i][j]))
print()
您在初始化 Rows 和 Cols 3D 列表时遇到浅拷贝问题。您需要像这样初始化它们,而不是使用乘法:
for k in range(n):
Rows.append([])
Cols.append([])
for l in range(n):
Rows[k].append([])
Cols[k].append([])
为了初始化列表的 3D 列表而进行乘法的问题是,里面的所有 n 个列表都指向同一个列表,所以当你附加到其中一个时,你附加到所有的列表,因为它们在技术上只是彼此的浅拷贝。因此,当您在最后打印它们时,所有列表都会添加所有数字,因为它们都指向内存中的同一个位置。通过使用上述方法初始化 3D 列表,您将在内存中的不同位置创建单独的列表,并将它们中的每一个插入到 Rows 和 Cols 3D 列表中。
看看当您执行以下操作时会发生什么:
x = [[]]*2
x[0].append(5)
输出:
[[5], [5]]
但如果您执行以下操作,问题就解决了:
x = [[],[]]
x[0].append(5)
输出:
[[5], []]
这里有一些其他人的解释比我的更好:
List of lists changes reflected across sublists unexpectedly
编辑:
这里有一个更好的 pythonic 方式来初始化行和列:
Rows = [[ [] for j in range(n)] for i in range(n)]
Cols = [[ [] for j in range(n)] for i in range(n)]