【问题标题】:Create 3D array using Python使用 Python 创建 3D 数组
【发布时间】:2012-05-26 22:55:47
【问题描述】:

我想在 Python (2.7) 中创建一个 3D 数组,以便像这样使用:

distance[i][j][k]

数组的大小应该是我拥有的变量的大小。 (nnn)

我尝试使用:

distance = [[[]*n]*n]

但这似乎不起作用。

我只能使用默认库,而乘法(即[[0]*n]*n)不起作用,因为它们链接到同一个指针,我需要所有值都是单独的

【问题讨论】:

  • 考虑使用标准array模块的array类。

标签: python arrays python-2.7 multidimensional-array


【解决方案1】:

正确的方法是

[[[0 for _ in range(n)] for _ in range(n)] for _ in range(n)]

(你想要做的应该写成(for NxNxN)

[[[0]*n]*n]*n

但这不正确,请参阅@Adaman 评论原因)。

【讨论】:

  • 不好。它将包含对同一数组的引用。试试这个:a = [[0] * 3] * 3; a[0][0] = 1; print a
【解决方案2】:

numpy.arrays 专为这种情况而设计:

 numpy.zeros((i,j,k))

会给你一个维度为 ijk 的数组,用零填充。

根据您的需要,numpy 可能是满足您需求的正确库。

【讨论】:

  • 哦,我还以为这是默认库之一。我不能使用除此之外的任何东西。
  • 不,不幸的是它是一个外部库。但如果您需要处理(大)数字数据数组,通常非常适合。特别是如果速度是一个问题。
  • 我定义了一个这样的数组:new_array= numpy.zeros((6340,200,200)) 但它占用了 1.9GB 的内存空间。正常吗?
  • @gocen 是的,听起来不错。 numpy zeroes 返回的默认值是 numpy.float64 和 6340*200*200*64bits = 2.0288 GB。您可以提供一个额外的参数 dtype 为零来更改它返回的类型并以这种方式节省一些 RAM。
【解决方案3】:

如果您坚持将所有内容初始化为空,则需要在内部使用一组额外的括号([[]] 而不是 [],因为这是“包含 1 个要复制的空列表的列表”而不是“一个不包含任何重复内容的列表”):

distance=[[[[]]*n]*n]*n

【讨论】:

  • 不要那样做,否则它们都会指向同一个引用!试试distance[1][2][0].append(1)
  • 是的,我的问题是如果我改变其中一个,它也会改变所有的。我需要它们是独立的元素。
【解决方案4】:

你应该使用list comprehension:

>>> import pprint
>>> n = 3
>>> distance = [[[0 for k in xrange(n)] for j in xrange(n)] for i in xrange(n)]
>>> pprint.pprint(distance)
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
 [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
 [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
>>> distance[0][1]
[0, 0, 0]
>>> distance[0][1][2]
0

您可以生成一个数据结构,其中包含一个看起来像您尝试过的语句的语句,但它会产生副作用,因为内部列表是按引用复制的:

>>> distance=[[[0]*n]*n]*n
>>> pprint.pprint(distance)
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
 [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
 [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
>>> distance[0][0][0] = 1
>>> pprint.pprint(distance)
[[[1, 0, 0], [1, 0, 0], [1, 0, 0]],
 [[1, 0, 0], [1, 0, 0], [1, 0, 0]],
 [[1, 0, 0], [1, 0, 0], [1, 0, 0]]]

【讨论】:

  • 对于 Python3,您可以将 xrange 更改为 range。
  • 我使用了'copy-by-reference'方法,却不知道后端实际发生了什么。因此,我最终得到了“副作用”(我的变量中的所有字段最终都具有相同的值)并且不知道为什么。谢谢你的解释。
【解决方案5】:
d3 = [[[0 for col in range(4)]for row in range(4)] for x in range(6)]

d3[1][2][1]  = 144

d3[4][3][0]  = 3.12

for x in range(len(d3)):
    print d3[x]



[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 144, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3.12, 0, 0, 0]]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

【讨论】:

    【解决方案6】:
    def n_arr(n, default=0, size=1):
        if n is 0:
            return default
    
        return [n_arr(n-1, default, size) for _ in range(size)]
    
    arr = n_arr(3, 42, 3)
    assert arr[2][2][2], 42
    

    【讨论】:

      【解决方案7】:
      """
      Create 3D array for given dimensions - (x, y, z)
      
      @author: Naimish Agarwal
      """
      
      
      def three_d_array(value, *dim):
          """
          Create 3D-array
          :param dim: a tuple of dimensions - (x, y, z)
          :param value: value with which 3D-array is to be filled
          :return: 3D-array
          """
      
          return [[[value for _ in xrange(dim[2])] for _ in xrange(dim[1])] for _ in xrange(dim[0])]
      
      if __name__ == "__main__":
          array = three_d_array(False, *(2, 3, 1))
          x = len(array)
          y = len(array[0])
          z = len(array[0][0])
          print x, y, z
      
          array[0][0][0] = True
          array[1][1][0] = True
      
          print array
      

      对于多维数组,首选使用numpy.ndarray

      【讨论】:

        【解决方案8】:

        您还可以使用嵌套的for 循环,如下所示

        n = 3
        arr = []
        for x in range(n):
            arr.append([])
            for y in range(n):
                arr[x].append([])
                for z in range(n):
                    arr[x][y].append(0)
        print(arr)
        

        【讨论】:

          【解决方案9】:

          有很多方法可以解决您的问题。

          1. @robert 接受的第一个答案。这里是广义的 解决方案:
          def multi_dimensional_list(value, *args):
            #args dimensions as many you like. EG: [*args = 4,3,2 => x=4, y=3, z=2]
            #value can only be of immutable type. So, don't pass a list here. Acceptable value = 0, -1, 'X', etc.
            if len(args) > 1:
              return [ multi_dimensional_list(value, *args[1:]) for col in range(args[0])]
            elif len(args) == 1: #base case of recursion
              return [ value for col in range(args[0])]
            else: #edge case when no values of dimensions is specified.
              return None
          

          例如:

          >>> multi_dimensional_list(-1, 3, 4)  #2D list
          [[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]
          >>> multi_dimensional_list(-1, 4, 3, 2)  #3D list
          [[[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]]]
          >>> multi_dimensional_list(-1, 2, 3, 2, 2 )  #4D list
          [[[[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]]], [[[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]]]]
          

          P.S 如果您热衷于验证 args 的正确值,即只有自然数,那么您可以在调用此函数之前编写一个包装函数。

          1. 其次,任何多维数组都可以写成一维数组。这意味着您不需要多维数组。下面是索引转换的函数:
          def convert_single_to_multi(value, max_dim):
            dim_count = len(max_dim)
            values = [0]*dim_count
            for i in range(dim_count-1, -1, -1): #reverse iteration
              values[i] = value%max_dim[i]
              value /= max_dim[i]
            return values
          
          
          def convert_multi_to_single(values, max_dim):
            dim_count = len(max_dim)
            value = 0
            length_of_dimension = 1
            for i in range(dim_count-1, -1, -1): #reverse iteration
              value += values[i]*length_of_dimension
              length_of_dimension *= max_dim[i]
            return value
          

          因为这些函数是互逆的,所以输出如下:

          >>> convert_single_to_multi(convert_multi_to_single([1,4,6,7],[23,45,32,14]),[23,45,32,14])
          [1, 4, 6, 7]
          >>> convert_multi_to_single(convert_single_to_multi(21343,[23,45,32,14]),[23,45,32,14])
          21343
          
          1. 如果您担心性能问题,那么您可以使用一些库,例如 pandas、numpy 等。

          【讨论】:

            【解决方案10】:
            n1=np.arange(90).reshape((3,3,-1))
            print(n1)
            print(n1.shape)
            

            【讨论】:

              猜你喜欢
              • 2020-06-10
              • 2016-09-03
              • 1970-01-01
              • 2021-03-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-12
              相关资源
              最近更新 更多