使用空子列表编制索引错误

时间:2015-08-18 20:34:11

标签: python list python-2.7 tree

我正在尝试实现树数据结构。我的树对象中的一个方法将节点与坐标相关联,同时将子节点映射到父节点&副节。

最初我给每个节点一个孩子的列表,结果证明是不正确的。因此,为了解决这个问题,我决定只使用空列表初始化节点,这就是故障开始的地方。

首先是有效的代码......

    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

那么为什么要添加空列表而不是占用列表更改索引?

遗憾的是,我没有权利共享其余的代码,我试图用简化的代码复制这个错误,但到目前为止还没有运气。

我怀疑这里有一些明显的东西,但是经过一天的怀疑之后盯着它,它的意义就越来越差。

1 个答案:

答案 0 :(得分:3)

我相信如果你打印

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), []]之类的内容,我认为你最好定义一个包含所有这些内容的对象。它将更容易调试。