将Python多维数组作为单个列表

1 投票
4 回答
1841 浏览
提问于 2025-04-16 10:12

当然,你可以用嵌套列表来表示多维数组,但这样做似乎会消耗很多资源...

[[0, 1], [2, 3]]

有没有什么方法可以把坐标“编码”和“解码”成一个数字,然后用这个数字来查找对应的元素呢?

[0, 1, 2, 3]

这个方法需要适用于多维的情况,不仅仅是二维的。我想到的编码方法是:

def getcellindex(self, location):
  cindex = 0
  cdrop = self.gridsize # where self.gridsize is the number of cells
  for index in xrange(self.numdimensions): # where self.numdimensions is the number of dimensions
    # where self.dimensions is a tuple of the different sizes of the corresponding dimension
    cdrop /= self.dimensions[index]
    cindex += cdrop * location[index]
  return cindex

可能还有其他优化的方法,但更重要的是,我该如何逆向这个过程呢?这个函数能正常工作吗?

4 个回答

0

如果你想要快速的数组,可以看看numpy数组,它们的速度非常快。否则,如果你有多个维度,比如n1, n2, n3, ..., nm,那么你可以用一个公式来表示数组中的元素,比如a[i][j][k]...[r]。这个公式是:i乘以(n2, n3, ...)的乘积,加上j乘以(n3, n4, ...)的乘积,再加上r。要反向操作,你需要对nm取模,这样就能得到r。然后你要减去r,再对nm乘以n(m-1)取模,依此类推。

3

你是不是因为担心性能问题而避开了明显的答案(比如 [[1, 2], [3, 4]])?如果是这样,而且你是在处理数字的话,可以看看NumPy数组。最好的办法就是别自己重新发明轮子。

编辑:如果你真的想按照自己的方式来做,可以参考NumPy的分步索引方案,大概可以这样做:

import operator
def product(lst):
    return reduce(operator.mul, lst, 1)

class MyArray(object):
    def __init__(self, shape, initval):
        self.shape = shape
        self.strides = [ product(shape[i+1:]) for i in xrange(len(shape)) ]
        self.data = [initval] * product(shape)

    def getindex(self, loc):
        return sum([ x*y for x, y in zip(self.strides, loc) ])

    def getloc(self, index):
        loc = tuple()
        for s in self.strides:
            i = index // s
            index = index % s
            loc += (i,)
        return loc

可以这样使用:

arr = MyArray((3, 2), 0)
arr.getindex((2, 1))
  -> 5
arr.getloc(5)
  -> (2, 1)
1
def getlocation(self, cellindex):
    res = []
    for size in reversed(self.dimensions):
        res.append(cellindex % size)
        cellindex /= size
    return res[::-1]
class ndim:
    def __init__(self):
        self.dimensions=[8,9,10]
        self.numdimensions=3
        self.gridsize=8*9*10

    def getcellindex(self, location):
        cindex = 0
        cdrop = self.gridsize
        for index in xrange(self.numdimensions):
            cdrop /= self.dimensions[index]
            cindex += cdrop * location[index]
        return cindex

    def getlocation(self, cellindex):
        res = []
        for size in reversed(self.dimensions):
            res.append(cellindex % size)
            cellindex /= size
        return res[::-1]

n=ndim()
print n.getcellindex((0,0,0))
print n.getcellindex((0,0,1))
print n.getcellindex((0,1,0))
print n.getcellindex((1,0,0))

print n.getlocation(90)
print n.getlocation(10)
print n.getlocation(1)
print n.getlocation(0)

或者,查看完整的测试案例

撰写回答