【问题标题】:Python Multidimensional Array as a single ListPython 多维数组作为单个列表
【发布时间】:2011-01-18 21:47:04
【问题描述】:

当然,您可以使用嵌套列表来表示多维数组,但这似乎代价高昂...

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

有没有办法将坐标“编码”和“解码”成一个数字,并使用该数字来查找相应的元素?

[0, 1, 2, 3]

这需要处理 n 维,而不仅仅是两个,我能想到的最好的编码是:

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

可能有一些方法可以优化这一点,但更重要的是,我该如何扭转这个过程?还有,这个功能有用吗?

【问题讨论】:

  • “看起来很昂贵”?这只是过早的优化吗?
  • 我会使用 numpy,但我需要它在 64 位 python 上工作,这似乎不适合我。
  • 为什么看起来很贵?您是否测试过并发现它很慢?这个问题的聪明答案可能最终会比嵌套列表慢。

标签: python list multidimensional-array


【解决方案1】:

您是否因为担心其性能而回避显而易见的答案(即[[1, 2], [3, 4]])?如果是这样并且您正在使用数字,请查看NumPy arrays。最好的解决方案是不要重新发明自己的轮子。

编辑: 如果您确实觉得有必要按照自己的方式进行操作,您可以像 NumPy 一样关注strided index scheme,它可能会变成这样:

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)

【讨论】:

    【解决方案2】:
    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)
    

    【讨论】:

    • 看来“for size in reversed(self.dimensions):”应该是“for size in self.dimensions”
    • @CMC:为什么?就目前的代码而言,我得到了正确的结果。您必须从最不重要的维度开始模块操作。
    • 不等...我错了。不过,我不太确定我是怎么做到的。
    【解决方案3】:

    如果您想要快速数组,您可能希望看到非常快的 numpy 数组。否则,如果你有维度 n1, n2, n3, ...,nm,那么你可以编码 a[i][j][k]...[r]: i * (product of (n2, n3... )) + j * ((n3, n4...) 的乘积) + r。逆向运算需要得到 nm 的模块,即 r,然后减去 r 并找到 nm*n(m-1) 的模块,依此类推。

    【讨论】:

      【解决方案4】:

      众所周知的双射:

      
      from itertools import tee
      
      def _basis(dimensions):
          # compute products of subtuple entries
          return tuple(reduce(lambda x,y: x*y, dimensions[:i]) for i in xrange(1, len(dimensions)+1))
      
      def coordinate(n, dimensions):
          basis = _basis(dimensions)
          residues = [n % b for b in basis]
          it2, it1 = tee(basis)
          for x in it2:
              break
          return (residues[0],) + tuple((m2-m1)/b in m2, m1, b in zip(it2, it1, basis))
      
      def number(c, dimensions):
          basis = _basis(dimensions)
          return sum(x*b for x, b in zip(c, basis))
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-30
        • 2017-06-16
        • 2013-05-17
        • 2013-02-09
        • 2020-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多