空子列表的索引错误
Indexing error with an empty sublist
我正在尝试实现树数据结构。我的树对象中的一种方法将节点与坐标相关联,同时将子节点映射到父节点,反之亦然。
最初我给每个节点一个子节点列表,结果证明是不正确的。所以为了补救,我决定只用一个空列表初始化节点,这就是问题开始的地方。
首先是有效的代码...
def treeSetUp(self):
'''Set tree's initial structure
For each level in treeArray
[level, leaf, [node number, parent, full, [coordinates], [centroid], [children]], [node number, leaf, full, [coordinates], [centroid], [children]], ...]'''
# Create root level & node
leaf = False
numChildren = (self.dims[0] * self.dims[1] * self.dims[2])/self.diameters[0]**3 # This maybe whay it only works for cubes
children = [(kids) for kids in xrange(numChildren)]
rootCoords = np.array([[0, 0, 0], [0, self.dims[0], 0], [self.dims[0], 0, 0], [self.dims[0], self.dims[1], 0], [0, 0, self.dims[2]], [0, self.dims[1], self.dims[2]], [self.dims[0], 0, self.dims[2]], [self.dims[0], self.dims[1], self.dims[2]]])
xCentroid = np.sum(rootCoords[:,0])/8.0
yCentroid = np.sum(rootCoords[:,1])/8.0
zCentroid = np.sum(rootCoords[:,2])/8.0
rootCentroids = [xCentroid, yCentroid, zCentroid]
rootNode = [0, None, False, rootCoords, rootCentroids, copy.copy(children)]
treeArray = []
treeArray.append([0, leaf, [rootNode]])
allCoordinates = []
allCoordinates.append(rootCoords)
allCentroids = []
allCentroids.append(rootCentroids)
for idx in xrange(self.depth):
# self.coordGenerator splits a given domain into cubes & returns the
# coordinates of each cube as well as its associated centroid
# This is done at different resolutions at different levels
levelCoordinates, levelCentroid = self.coordGenerator(idx+1)
allCoordinates.append(levelCoordinates)
allCentroids.append(levelCentroid)
nodeCount = 0
if idx == self.depth-1:
leaf = True
# Generate level's nodes
newNodes = []
for parentNode, node in enumerate(treeArray[idx][2]):
# Generate nodes's child list
children = []
for nodeNumber, child in enumerate(node[5]):
# Gereate child list
if leaf:
children = [None]
else:
numChildren = (self.diameters[idx]**3)/(self.diameters[idx+1]**3)
children = [(kids + nodeCount*numChildren) for kids in xrange(numChildren)]
# Assign coordinates to level 1 nodes else generate placeholders
if idx == 0:
nodeCoords = levelCoordinates[nodeNumber]
nodeCentroid = levelCentroid[nodeNumber]
else:
nodeCoords = []
nodeCentroid = []
newNodes.append([nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), copy.copy(children)])
nodeCount += 1
newLevel = [idx+1, leaf, copy.deepcopy(newNodes)]
treeArray.append(newLevel)
# Operation find parents
for level in xrange(1, self.depth):
for childNode, centroid in enumerate(allCentroids[level+1]):
for node in treeArray[level][2]:
# bounding box of parent node
boundary = node[3]
xBound = [np.min(boundary[:,0]), np.max(boundary[:,0])]
yBound = [np.min(boundary[:,1]), np.max(boundary[:,1])]
zBound = [np.min(boundary[:,2]), np.max(boundary[:,2])]
# Is child's centroid in parents ounding box?
if (xBound[0] <= centroid[0] <= xBound[1]) and (yBound[0] <= centroid[1] <= yBound[1]) and (zBound[0] <= centroid[2] <= zBound[1]):
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child
treeArray[level+1][2][childNode][3] = allCoordinates[level+1][childNode]
treeArray[level+1][2][childNode][4] = centroid
# treeArray[level][2][node[0]][5].append(childNode) # Add child to parents list of children
break
现在代码不...
def treeSetUp(self):
'''Set tree's initial structure
For each level in treeArray
[level, leaf, [node number, parent, full, [coordinates], [centroid], [children]], [node number, leaf, full, [coordinates], [centroid], [children]], ...]'''
# Create root level & node
leaf = False
numChildren = (self.dims[0] * self.dims[1] * self.dims[2])/self.diameters[0]**3 # This maybe whay it only works for cubes
children = [(kids) for kids in xrange(numChildren)]
rootCoords = np.array([[0, 0, 0], [0, self.dims[0], 0], [self.dims[0], 0, 0], [self.dims[0], self.dims[1], 0], [0, 0, self.dims[2]], [0, self.dims[1], self.dims[2]], [self.dims[0], 0, self.dims[2]], [self.dims[0], self.dims[1], self.dims[2]]])
xCentroid = np.sum(rootCoords[:,0])/8.0
yCentroid = np.sum(rootCoords[:,1])/8.0
zCentroid = np.sum(rootCoords[:,2])/8.0
rootCentroids = [xCentroid, yCentroid, zCentroid]
rootNode = [0, None, False, rootCoords, rootCentroids, copy.copy(children)]
treeArray = []
treeArray.append([0, leaf, [rootNode]])
allCoordinates = []
allCoordinates.append(rootCoords)
allCentroids = []
allCentroids.append(rootCentroids)
for idx in xrange(self.depth):
# self.coordGenerator splits a given domain into cubes & returns the
# coordinates of each cube as well as its associated centroid
# This is done at different resolutions at different levels
levelCoordinates, levelCentroid = self.coordGenerator(idx+1)
allCoordinates.append(levelCoordinates)
allCentroids.append(levelCentroid)
nodeCount = 0
if idx == self.depth-1:
leaf = True
# Generate level's nodes
newNodes = []
for parentNode, node in enumerate(treeArray[idx][2]):
# Generate nodes's child list
children = []
for nodeNumber, child in enumerate(node[5]):
# Gereate child list
if leaf:
children = [None]
else:
numChildren = (self.diameters[idx]**3)/(self.diameters[idx+1]**3)
children = [(kids + nodeCount*numChildren) for kids in xrange(numChildren)]
# Assign coordinates to level 1 nodes else generate placeholders
if idx == 0:
nodeCoords = levelCoordinates[nodeNumber]
nodeCentroid = levelCentroid[nodeNumber]
else:
nodeCoords = []
nodeCentroid = []
newNodes.append([nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), []]) #copy.copy(children)])
nodeCount += 1
newLevel = [idx+1, leaf, copy.deepcopy(newNodes)]
treeArray.append(newLevel)
# Operation find parents
for level in xrange(1, self.depth):
for childNode, centroid in enumerate(allCentroids[level+1]):
for node in treeArray[level][2]:
# bounding box of parent node
boundary = node[3]
xBound = [np.min(boundary[:,0]), np.max(boundary[:,0])]
yBound = [np.min(boundary[:,1]), np.max(boundary[:,1])]
zBound = [np.min(boundary[:,2]), np.max(boundary[:,2])]
# Is child's centroid in parents ounding box?
if (xBound[0] <= centroid[0] <= xBound[1]) and (yBound[0] <= centroid[1] <= yBound[1]) and (zBound[0] <= centroid[2] <= zBound[1]):
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child
treeArray[level+1][2][childNode][3] = allCoordinates[level+1][childNode]
treeArray[level+1][2][childNode][4] = centroid
# treeArray[level][2][node[0]][5].append(childNode) # Add child to parents list of children
break
唯一的区别是我没有提供错误的子节点列表,而是提供了一个空列表。
它给出的错误..
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child IndexError: list index out of range
那么为什么添加空列表而不是占用列表会更改索引?
不幸的是,我无权分享其余代码,我曾尝试在简化代码中重现此错误,但到目前为止没有成功。
我怀疑这里有一些明显的东西,但在怀疑地盯着它看了一天之后,它变得不那么有意义了。
我相信如果你打印
treeArray[level+1][2][childNode]
就在发生错误的行之前,您会发现代码中的 []
不起作用,并且等于代码中起作用的其他内容。因此,当您将 ...[childNode][1]
设置为具有值时,您会 运行 陷入与设置
时相同的错误
a = []
a[1]=1
> IndexError: list assignment index out of range
而在工作代码中您会看到如下内容:
a=[4,6]
a[1]=1
print a
>[4,1]
当您不向它发送一个空列表,而是一个子项的副本时,当它尝试设置该条目时,它会成功,因为该条目已经在列表中,它只是更改值.另一方面,如果它试图设置空列表的 [1] 条目,那么它将失败,因为列表条目尚不存在。将 a[n]=x
视为提交更改 a[n]
身份所需的法律表格。如果您为不存在的人提交表格,则该过程不起作用。实际创建 a[n]
需要一些其他过程。
您应该大大简化代码。与其拥有诸如 [nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), []]
之类的列表,我认为您最好定义一个包含所有这些的对象。调试起来会更容易。
我正在尝试实现树数据结构。我的树对象中的一种方法将节点与坐标相关联,同时将子节点映射到父节点,反之亦然。
最初我给每个节点一个子节点列表,结果证明是不正确的。所以为了补救,我决定只用一个空列表初始化节点,这就是问题开始的地方。
首先是有效的代码...
def treeSetUp(self):
'''Set tree's initial structure
For each level in treeArray
[level, leaf, [node number, parent, full, [coordinates], [centroid], [children]], [node number, leaf, full, [coordinates], [centroid], [children]], ...]'''
# Create root level & node
leaf = False
numChildren = (self.dims[0] * self.dims[1] * self.dims[2])/self.diameters[0]**3 # This maybe whay it only works for cubes
children = [(kids) for kids in xrange(numChildren)]
rootCoords = np.array([[0, 0, 0], [0, self.dims[0], 0], [self.dims[0], 0, 0], [self.dims[0], self.dims[1], 0], [0, 0, self.dims[2]], [0, self.dims[1], self.dims[2]], [self.dims[0], 0, self.dims[2]], [self.dims[0], self.dims[1], self.dims[2]]])
xCentroid = np.sum(rootCoords[:,0])/8.0
yCentroid = np.sum(rootCoords[:,1])/8.0
zCentroid = np.sum(rootCoords[:,2])/8.0
rootCentroids = [xCentroid, yCentroid, zCentroid]
rootNode = [0, None, False, rootCoords, rootCentroids, copy.copy(children)]
treeArray = []
treeArray.append([0, leaf, [rootNode]])
allCoordinates = []
allCoordinates.append(rootCoords)
allCentroids = []
allCentroids.append(rootCentroids)
for idx in xrange(self.depth):
# self.coordGenerator splits a given domain into cubes & returns the
# coordinates of each cube as well as its associated centroid
# This is done at different resolutions at different levels
levelCoordinates, levelCentroid = self.coordGenerator(idx+1)
allCoordinates.append(levelCoordinates)
allCentroids.append(levelCentroid)
nodeCount = 0
if idx == self.depth-1:
leaf = True
# Generate level's nodes
newNodes = []
for parentNode, node in enumerate(treeArray[idx][2]):
# Generate nodes's child list
children = []
for nodeNumber, child in enumerate(node[5]):
# Gereate child list
if leaf:
children = [None]
else:
numChildren = (self.diameters[idx]**3)/(self.diameters[idx+1]**3)
children = [(kids + nodeCount*numChildren) for kids in xrange(numChildren)]
# Assign coordinates to level 1 nodes else generate placeholders
if idx == 0:
nodeCoords = levelCoordinates[nodeNumber]
nodeCentroid = levelCentroid[nodeNumber]
else:
nodeCoords = []
nodeCentroid = []
newNodes.append([nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), copy.copy(children)])
nodeCount += 1
newLevel = [idx+1, leaf, copy.deepcopy(newNodes)]
treeArray.append(newLevel)
# Operation find parents
for level in xrange(1, self.depth):
for childNode, centroid in enumerate(allCentroids[level+1]):
for node in treeArray[level][2]:
# bounding box of parent node
boundary = node[3]
xBound = [np.min(boundary[:,0]), np.max(boundary[:,0])]
yBound = [np.min(boundary[:,1]), np.max(boundary[:,1])]
zBound = [np.min(boundary[:,2]), np.max(boundary[:,2])]
# Is child's centroid in parents ounding box?
if (xBound[0] <= centroid[0] <= xBound[1]) and (yBound[0] <= centroid[1] <= yBound[1]) and (zBound[0] <= centroid[2] <= zBound[1]):
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child
treeArray[level+1][2][childNode][3] = allCoordinates[level+1][childNode]
treeArray[level+1][2][childNode][4] = centroid
# treeArray[level][2][node[0]][5].append(childNode) # Add child to parents list of children
break
现在代码不...
def treeSetUp(self):
'''Set tree's initial structure
For each level in treeArray
[level, leaf, [node number, parent, full, [coordinates], [centroid], [children]], [node number, leaf, full, [coordinates], [centroid], [children]], ...]'''
# Create root level & node
leaf = False
numChildren = (self.dims[0] * self.dims[1] * self.dims[2])/self.diameters[0]**3 # This maybe whay it only works for cubes
children = [(kids) for kids in xrange(numChildren)]
rootCoords = np.array([[0, 0, 0], [0, self.dims[0], 0], [self.dims[0], 0, 0], [self.dims[0], self.dims[1], 0], [0, 0, self.dims[2]], [0, self.dims[1], self.dims[2]], [self.dims[0], 0, self.dims[2]], [self.dims[0], self.dims[1], self.dims[2]]])
xCentroid = np.sum(rootCoords[:,0])/8.0
yCentroid = np.sum(rootCoords[:,1])/8.0
zCentroid = np.sum(rootCoords[:,2])/8.0
rootCentroids = [xCentroid, yCentroid, zCentroid]
rootNode = [0, None, False, rootCoords, rootCentroids, copy.copy(children)]
treeArray = []
treeArray.append([0, leaf, [rootNode]])
allCoordinates = []
allCoordinates.append(rootCoords)
allCentroids = []
allCentroids.append(rootCentroids)
for idx in xrange(self.depth):
# self.coordGenerator splits a given domain into cubes & returns the
# coordinates of each cube as well as its associated centroid
# This is done at different resolutions at different levels
levelCoordinates, levelCentroid = self.coordGenerator(idx+1)
allCoordinates.append(levelCoordinates)
allCentroids.append(levelCentroid)
nodeCount = 0
if idx == self.depth-1:
leaf = True
# Generate level's nodes
newNodes = []
for parentNode, node in enumerate(treeArray[idx][2]):
# Generate nodes's child list
children = []
for nodeNumber, child in enumerate(node[5]):
# Gereate child list
if leaf:
children = [None]
else:
numChildren = (self.diameters[idx]**3)/(self.diameters[idx+1]**3)
children = [(kids + nodeCount*numChildren) for kids in xrange(numChildren)]
# Assign coordinates to level 1 nodes else generate placeholders
if idx == 0:
nodeCoords = levelCoordinates[nodeNumber]
nodeCentroid = levelCentroid[nodeNumber]
else:
nodeCoords = []
nodeCentroid = []
newNodes.append([nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), []]) #copy.copy(children)])
nodeCount += 1
newLevel = [idx+1, leaf, copy.deepcopy(newNodes)]
treeArray.append(newLevel)
# Operation find parents
for level in xrange(1, self.depth):
for childNode, centroid in enumerate(allCentroids[level+1]):
for node in treeArray[level][2]:
# bounding box of parent node
boundary = node[3]
xBound = [np.min(boundary[:,0]), np.max(boundary[:,0])]
yBound = [np.min(boundary[:,1]), np.max(boundary[:,1])]
zBound = [np.min(boundary[:,2]), np.max(boundary[:,2])]
# Is child's centroid in parents ounding box?
if (xBound[0] <= centroid[0] <= xBound[1]) and (yBound[0] <= centroid[1] <= yBound[1]) and (zBound[0] <= centroid[2] <= zBound[1]):
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child
treeArray[level+1][2][childNode][3] = allCoordinates[level+1][childNode]
treeArray[level+1][2][childNode][4] = centroid
# treeArray[level][2][node[0]][5].append(childNode) # Add child to parents list of children
break
唯一的区别是我没有提供错误的子节点列表,而是提供了一个空列表。
它给出的错误..
treeArray[level+1][2][childNode][1] = node[0] # Add parent node to child IndexError: list index out of range
那么为什么添加空列表而不是占用列表会更改索引?
不幸的是,我无权分享其余代码,我曾尝试在简化代码中重现此错误,但到目前为止没有成功。
我怀疑这里有一些明显的东西,但在怀疑地盯着它看了一天之后,它变得不那么有意义了。
我相信如果你打印
treeArray[level+1][2][childNode]
就在发生错误的行之前,您会发现代码中的 []
不起作用,并且等于代码中起作用的其他内容。因此,当您将 ...[childNode][1]
设置为具有值时,您会 运行 陷入与设置
a = []
a[1]=1
> IndexError: list assignment index out of range
而在工作代码中您会看到如下内容:
a=[4,6]
a[1]=1
print a
>[4,1]
当您不向它发送一个空列表,而是一个子项的副本时,当它尝试设置该条目时,它会成功,因为该条目已经在列表中,它只是更改值.另一方面,如果它试图设置空列表的 [1] 条目,那么它将失败,因为列表条目尚不存在。将 a[n]=x
视为提交更改 a[n]
身份所需的法律表格。如果您为不存在的人提交表格,则该过程不起作用。实际创建 a[n]
需要一些其他过程。
您应该大大简化代码。与其拥有诸如 [nodeCount, parentNode, False, copy.deepcopy(nodeCoords), copy.deepcopy(nodeCentroid), []]
之类的列表,我认为您最好定义一个包含所有这些的对象。调试起来会更容易。