【问题标题】:Multidimensional array in PythonPython中的多维数组
【发布时间】:2010-10-05 06:02:39
【问题描述】:

我有一点 Java 问题,我想翻译成 Python。因此我需要一个多维数组。在 Java 中它看起来像:

double dArray[][][] = new double[x.length()+1][y.length()+1][x.length()+y.length()+3];
dArray[0][0][0] = 0;
dArray[0][0][1] = POSITIVE_INFINITY;

将在循环中创建更多值并将其写入数组。

如何实例化数组?

PS:不涉及矩阵乘法...

【问题讨论】:

  • 顺便说一句,您可以在 python 中以float('inf') 获得浮点无穷大。它的行为或多或少如你所料——大多数操作只给你 inf,少数给你 nan。
  • (与之前的问题合并;将其作为主人保留 a:OP 仍然存在,b:问题措辞更好,c:避免大量死灵法师)

标签: java python arrays


【解决方案1】:

如果您限制自己使用 Python 标准库,那么列表列表是最接近的构造:

arr = [[1,2],[3,4]]

给出一个二维数组。行可以以arr[i] 访问i 中的{0,..,len(arr},但列访问很困难。

如果您愿意添加库依赖项,NumPy 包是您真正想要的。您可以使用以下方法从列表列表中创建一个固定长度的数组:

import numpy
arr = numpy.array([[1,2],[3,4]])

列访问与列表列表相同,但列访问很容易:arr[:,i] 用于 {0,..,arr.shape[1]} 中的 i(列数)。

事实上,NumPy 数组可以是 n 维的。

可以创建空数组

numpy.empty(shape)

其中shape 是每个维度中大小的元组; shape=(1,3,2) 给出一个 3-d 数组,第一维大小为 1,第二维大小为 3,第三维大小为 2。

如果您想将对象存储在 NumPy 数组中,您也可以这样做:

 arr = numpy.empty((1,), dtype=numpy.object)
 arr[0] = 'abc'

有关 NumPy 项目的更多信息,请查看NumPy homepage

【讨论】:

  • 不需要使用元组。 numpy.empty([1]) 也可以。
  • 简单的“随机”数字生成器:noise = lambda: numpy.empty([1])[0]
  • 没错,任何可迭代的(列表、元组等)都可以作为维度参数。您的“随机”数字生成器依赖于未初始化的“随机”内存,并且应该永远用作任何重要事物(例如密码学)的随机源。
  • @Barry:没错,这就是为什么我在random周围加上引号
  • @JFSebastian:我相信你知道其中的区别。只是想确保谷歌也这样做了,为了后代等等。
【解决方案2】:

创建任意大小数组的标准python数组:

a = [[0]*cols for _ in [0]*rows]

访问方式如下:

a[0][1] = 5 # set cell at row 0, col 1 to 5

一个值得一提的小蟒蛇陷阱:只需键入即可

a = [[0]*cols]*rows

但这会将 same 列数组复制到每一行,从而导致不需要的行为。即:

>>> a[0][0] = 5
>>> print a[1][0]
5

【讨论】:

  • 我宁愿使用:[[0]*cols for _ in xrange(rows)]
  • @J.F.Sebastian 我也是,真的。在撰写本文时,我刚刚发现对称性很有吸引力。 :-)
  • 加 1 个问题。
【解决方案3】:

您可以使用嵌套列表创建它:

matrix = [[a,b],[c,d],[e,f]]

如果它必须是动态的,那就更复杂了,为什么不自己写一个小类呢?

class Matrix(object):
    def __init__(self, rows, columns, default=0):
        self.m = []
        for i in range(rows):
            self.m.append([default for j in range(columns)])

    def __getitem__(self, index):
        return self.m[index]

可以这样使用:

m = Matrix(10,5)
m[3][6] = 7
print m[3][6] // -> 7

我确信可以更有效地实施它。 :)

如果您需要多维数组,您可以创建一个数组并计算偏移量,或者您可以在数组中的数组中使用数组,这对内存非常不利。 (虽然可能更快......)我已经实现了这样的第一个想法:

class Matrix(object):
    def __init__(self, *dims):
        self._shortcuts = [i for i in self._create_shortcuts(dims)]
        self._li = [None] * (self._shortcuts.pop())
        self._shortcuts.reverse()

    def _create_shortcuts(self, dims):
        dimList = list(dims)
        dimList.reverse()
        number = 1
        yield 1
        for i in dimList:
            number *= i
            yield number

    def _flat_index(self, index):
        if len(index) != len(self._shortcuts):
            raise TypeError()

        flatIndex = 0
        for i, num in enumerate(index):
            flatIndex += num * self._shortcuts[i]
        return flatIndex

    def __getitem__(self, index):
        return self._li[self._flat_index(index)]

    def __setitem__(self, index, value):
        self._li[self._flat_index(index)] = value

可以这样使用:

m = Matrix(4,5,2,6)
m[2,3,1,3] = 'x'
m[2,3,1,3] // -> 'x'

【讨论】:

    【解决方案4】:

    看看numpy

    这里有一个代码 sn-p 给你

    import numpy as npy
    
    d = npy.zeros((len(x)+1, len(y)+1, len(x)+len(y)+3))
    d[0][0][0] = 0 # although this is unnecessary since zeros initialises to zero
    d[i][j][k] = npy.inf
    

    我认为您不需要实施科学应用程序来证明使用 numpy.它更快、更灵活,您几乎可以存储任何东西。鉴于我认为尝试并证明 使用它可能会更好。有正当的理由,但它增加了很多,而且成本很低,因此值得考虑。

    附:你的数组长度正确吗?它看起来像一个形状奇特的矩阵......

    【讨论】:

      【解决方案5】:

      多维数组有点模糊。使用它们的原因很少,而需要三思而后行并使用更能反映您正在做的事情的其他东西的原因很多。 [暗示。你的问题在上下文中很薄弱;-)]

      如果您正在做矩阵数学,请使用numpy

      但是,有些人使用的语言迫使他们使用多维数组,因为这就是他们所拥有的一切。如果您和我一样大(我在 70 年代开始编程),那么您可能还记得多维数组是您拥有的唯一数据结构的日子。或者,您的经验可能将您限制在必须将问题转化为多维数组的语言中。

      假设您有一个集合 n 个 3D 点。每个点都有一个 x、y、z 和时间值。这是一个 n x 4 数组吗?还是一个 4 * n 数组?并不真地。

      因为每个点都有 4 个固定值,所以这更恰当地是一个元组列表。

      a = [ ( x, y, z, t ), ( x, y, z, t ), ... ]
      

      更好的是,我们可以将其表示为对象列表。

      class Point( object ):
          def __init__( self, x, y, z, t ):
              self.x, self.y, self.z, self.t = x, y, z, t
      
      a = [ Point(x,y,x,t), Point(x,y,z,t), ... ]
      

      【讨论】:

        【解决方案6】:

        如果您可以使用稀疏数组,您可以使用 dict 来存储您的值。 Python 的 dicts 允许您使用元组作为键,因此,您可以像这样分配和访问“稀疏数组”(这里实际上是一个 dict)的元素:

        d = {}
        d[0,2,7] = 123 # assign 123 to x=0, y=2, z=7
        v = d[0,2,7]
        

        【讨论】:

        • 存储多维数组的好技巧。然而,当尝试迭代元素时,比如列或行,甚至能够获得“维度”,事情会变得非常混乱。
        • 确实如此。如果我要使用这样的东西,我当然会把它封装到一个类中并引入读/写访问的方法。实例变量将存储数组的维度,读/写方法将返回未分配元素的默认值(通过捕获 KeyError)。
        • +1:字典相当简单。维度的迭代很容易,而不是混乱。 xRange = set( [ k[0] for k in d.keys() ] ), yRange = set( [ k[1] for k in d.keys() ] )
        • @S.Lott:我所说的混乱的意思是,你建议的迭代只有在你填充了这个多维数组的所有元素时才有效,但是如果你有“空白”,这根本不会不工作。无论如何 +1 辣椒粉以获得原始解决方案。
        【解决方案7】:

        可能与您无关,但如果您正在做认真的矩阵工作,请参阅numpy

        【讨论】:

          【解决方案8】:

          对于数值数据,Numpy Arrays:

          >>> matrix1 = array(([0,1],[1,3]))
          >>> print matrix1
          [[0 1]
          [1 3]]
          

          对于一般数据(例如字符串),您可以使用列表列表、元组列表...

          matrix2 = [['a','b'], ['x','y']]
          

          【讨论】:

          • 我可以像在 C 中那样将它初始化为给定数量的行和列吗?
          • 可变对象(例如列表)可以改变 - 所以初始化并不总是相关的。在 numpy 中,Array 有一个 Shape(维度),可以在不更改数据的情况下进行修改。
          • @Popper:是的。 zeros( (3,4) ) 将创建一个 3x4 的零数组。
          【解决方案9】:

          以下是创建用零初始化的嵌套 3 维列表的快速方法:

          # dim1, dim2, dim3 are the dimensions of the array
          a =[[[0 for _ in range(dim1)] for _ in range(dim2)] for _ in range(dim1) ]
          a[0][0][0] = 1
          

          这是一个列表的列表,比数组灵活一点,你可以这样做:

          a[0][0] = [1,2,3,4]
          

          替换数组中的一整行,甚至像这样滥用它:

          a[0] = "Ouch"
          print a[0][0] #will print "O", since strings are indexable the same way as lists
          print a[0][0][0] #will raise an error, since "O" isn't indexable
          

          但如果您需要性能,那么我同意 numpy 是要走的路。

          另外,请注意:

          a = [[[0] * 5]*5]*5]
          

          如果你在上面的对象上尝试a[0][0][0]=7,你会发现有什么问题。

          【讨论】:

            【解决方案10】:

            另一种选择是使用字典:

            >>> from collections import defaultdict
            >>> array = defaultdict(int) # replace int with the default-factory you want
            >>> array[(0,0)]
            0
            >>> array[(99,99)]
            0
            

            您还需要跟踪上限和下限。

            【讨论】:

              【解决方案11】:

              我刚刚遇到了类似的需求并编写了以下代码:

              def nDimensionsMatrix(dims, elem_count, ptr=[]):
                  if (dims > 1):
                      for i in range(elem_count[dims-1]):
                          empty = []
                          ptr.append(empty)
                          nDimensionsMatrix(dims-1, elem_count, empty)
                      return ptr
                  elif dims == 1:
                      ptr.extend([0 for i in range(elem_count[dims])])
                      return ptr
              
              matrix = nDimensionsMatrix(3, (2,2,2))
              

              我不看速度,只看功能;)

              我想创建一个具有 N 维的矩阵并用 0 进行初始化(每个维度中有一个 elem_count 个元素)。

              希望对某人有所帮助

              【讨论】:

                【解决方案12】:

                简单,使用 numpy 时:

                b = ones((2,3,4)) # creates a 2x3x4 array containing all ones.
                

                “ones”可以替换为“zeros”

                【讨论】:

                  猜你喜欢
                  • 2014-05-21
                  • 2016-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-07-06
                  • 1970-01-01
                  • 2016-11-01
                  • 1970-01-01
                  • 2021-04-15
                  相关资源
                  最近更新 更多