【问题标题】:Python 2.7 creating a multidimensional listPython 2.7 创建多维列表
【发布时间】:2012-11-07 00:36:46
【问题描述】:

在 Python 中,我想要一种直观的方式来创建 3 维列表。

我想要一个 (n × n) 列表。所以对于 n = 4 它应该是:

x = [[[],[],[],[]],[[],[],[],[]],[[],[],[],[]],[[],[],[],[]]]

我尝试过使用:

y = [n*[n*[]]]    
y = [[[]]* n for i in range(n)]

两者似乎都在创建引用的副本。 我也尝试过简单地应用列表生成器,但收效甚微:

y = [[[]* n for i in range(n)]* n for i in range(n)]
y = [[[]* n for i in range(1)]* n for i in range(n)]

我还尝试使用循环迭代地构建数组,但没有成功。我也试过这个:

y = []
for i in range(0,n):
    y.append([[]*n for i in range(n)])

有没有更简单或更直观的方法?

【问题讨论】:

  • 对多维数组/列表使用 numpy 可以省去很多麻烦。

标签: python list python-2.7 list-comprehension


【解决方案1】:

我认为您的列表理解版本非常接近工作。您不需要进行任何列表乘法(无论如何它都不适用于空列表)。这是一个工作版本:

>>> y = [[[] for i in range(n)] for i in range(n)]
>>> print y
[[[], [], [], []], [[], [], [], []], [[], [], [], []], [[], [], [], []]]

【讨论】:

    【解决方案2】:

    看起来最简单的方法如下:

    def create_empty_array_of_shape(shape):
        if shape: return [create_empty_array_of_shape(shape[1:]) for i in xrange(shape[0])]
    

    对我有用

    【讨论】:

      【解决方案3】:

      我发现了这个:

      Matrix = [[0 for x in xrange(5)] for x in xrange(5)]
      

      您现在可以将项目添加到列表中:

      Matrix[0][0] = 1
      Matrix[4][0] = 5
      
      print Matrix[0][0] # prints 1
      print Matrix[4][0] # prints 5
      

      从这里:How to define two-dimensional array in python

      【讨论】:

      • 那是我的,在你编辑之前。我现在已将其删除,因为您的回答现在至少是明智的。我认为这在技术上仍然是错误的,因为提问者特别想要n by n by 0 三维结构,而您只是在制作n by n 二维结构。
      • 很公平。但是这个答案可以很容易地扩展到 3D,不是吗?或者我误解了这个问题。
      【解决方案4】:

      一个非常简单优雅的方式是:

      a = [([0] * 5) for i in range(5)]
      a
      [[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]]
      

      【讨论】:

        【解决方案5】:

        在 Python 中,我创建了一个小工厂方法来创建可变维度和每个维度上可变大小的列表:

        def create_n_dimensional_matrix(self, n):
          dimensions = len(n)
          if (dimensions == 1): 
            return [0 for i in range(n[0])]
        
          if (dimensions == 2): 
            return [[0 for i in range(n[0])] for j in range(n[1])]
        
          if (dimensions == 3): 
            return [[[0 for i in range(n[0])] for j in range(n[1])] for k in range(n[2])]
        
          if (dimensions == 4): 
            return [[[[0 for i in range(n[0])] for j in range(n[1])] for k in range(n[2])] for l in range(n[3])]
        

        像这样运行它:

        print(str(k.create_n_dimensional_matrix([2,3])))
        print(str(k.create_n_dimensional_matrix([3,2])))
        print(str(k.create_n_dimensional_matrix([1,2,3])))
        print(str(k.create_n_dimensional_matrix([3,2,1])))
        print(str(k.create_n_dimensional_matrix([2,3,4,5])))
        print(str(k.create_n_dimensional_matrix([5,4,3,2])))    
        

        哪些打印:

        1. 二维列表 (2x3), (3x2)
        2. 三维列表 (1x2x3),(3x2x1)
        3. 四维列表(2x3x4x5),(5x4x3x2)

          [[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], [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], [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, 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, 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, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]]]
          

        【讨论】:

          【解决方案6】:

          这个怎么样:

          class MultiDimList(object):
              def __init__(self, shape):
                  self.shape = shape
                  self.L = self._createMultiDimList(shape)
              def get(self, ind):
                  if(len(ind) != len(self.shape)): raise IndexError()
                  return self._get(self.L, ind)
              def set(self, ind, val):
                  if(len(ind) != len(self.shape)): raise IndexError()
                  return self._set(self.L, ind, val)
              def _get(self, L, ind):
                  return self._get(L[ind[0]], ind[1:]) if len(ind) > 1 else L[ind[0]]
              def _set(self, L, ind, val):
                  if(len(ind) > 1): 
                      self._set(L[ind[0]], ind[1:], val) 
                  else: 
                      L[ind[0]] = val
              def _createMultiDimList(self, shape):
                  return [self._createMultiDimList(shape[1:]) if len(shape) > 1 else None for _ in range(shape[0])]
              def __repr__(self):
                  return repr(self.L)
          

          然后你可以如下使用它

          L = MultiDimList((3,4,5)) # creates a 3x4x5 list
          L.set((0,0,0), 1)
          L.get((0,0,0))
          

          【讨论】:

            【解决方案7】:
            import copy
            dimensions = 2, 3, 4
            z = 0
            genList = lambda size,value: [copy.deepcopy(value) for i in range(size)]
            for i in dimensions: z = genList(i, z)
            

            【讨论】:

              【解决方案8】:

              我很惊讶没有人试图设计一种通用的方法来做到这一点。 在这里查看我的答案:https://stackoverflow.com/a/33460217/5256940

              import copy
              
              def ndlist(init, *args):  # python 2 doesn't have kwarg after *args
                  dp = init
                  for x in reversed(args):
                      dp = [copy.deepcopy(dp) for _ in xrange(x)] # Python 2 xrange
                  return dp
              
              l = ndlist(0, 1, 2, 3, 4) # 4 dimensional list initialized with 0's
              l[0][1][2][3] = 1
              

              编辑:基于 user2114402 的回答:添加了默认值参数

              def ndlist(s, v):
                  return [ndlist(s[1:], v) for i in xrange(s[0])] if s else v
              

              【讨论】:

              • 我不确定 SO 是否应该更智能地处理交叉链接 :)
              • 可能。反正我已经删除了我的评论,因为它不再适用...... :)
              • 查看 user2114402 的回答。这是比您早两年发布的通用方式。 “我很惊讶没有人”阅读以前发布的答案;-)。
              • 哎呀...错过了:D。我最初发布了另一个问题的答案,并在此处复制了该答案。为简短的递归答案投票赞成 user2114402。
              • 我对这个问题的更通用的答案很感兴趣。假设我们有 N 个维度,我们需要获取和设置一个元素。获取一个元素将是一个相对简单的递归,而设置一个元素并不是那么容易(如果我错了,请纠正我)。 "l[1][1][1]" 行不通,因为我们事先不知道维数。
              【解决方案9】:

              这里会给你一个 N 维“矩阵”,里面填满了可复制对象的副本。

              编辑:这是对 pterodragon 原始答案的轻微修改,我更喜欢 user2114402 的可读性较差的答案。事实上,在文档字符串之外,与 pterodragon 解决方案的唯一区别是我明确使用了尺寸大小列表,而不是让用户将它们作为参数传递。

              import copy
              
                  def instantiate_mdl(dim_maxes, base=0):
                      """ Instantiate multi-dimensional list, that is a list of list of list ...
              
                      Arguments:
                          dim_maxes (list[int]): a list of dimension sizes, for example 
                          [2, 4] represents a matrix (represented by lists) of 2 rows and 
                          4 columns.     
              
                          base (object): an optional argument indicating the object copies
                          of which will reside at the lowest level in the datastructure.
                      Returns:
                          base (list[base]): a multi-dimensional list of lists structure,
                          which is filled with clones of the base parameter.
                      """
                      for dim_max in reversed(dim_maxes):
                          base = [copy.deepcopy(base) for i in range(dim_max)]
                      return base
              
              data = instantiate_mdl([3, 5])
              data[0][0] = 99999
              data[1][1] = 88888
              data[2][4] = 77777
              
              for r in data:
                  print(r)
              
              >>> # Output
              >>> [99999, 0, 0, 0, 0]
              >>> [0, 88888, 0, 0, 0]
              >>> [0, 0, 0, 0, 77777]
              

              【讨论】:

                【解决方案10】:

                这是一种更通用的方法。

                def ndlist(shape, dtype=list):
                    t = '%s for v%d in xrange(shape[%d])'
                    cmd = [t % ('%s', i + 1, i) for i in xrange(len(shape))]
                    cmd[-1] = cmd[-1] % str(dtype())
                    for i in range(len(cmd) - 1)[::-1]:
                        cmd[i] = cmd[i] % ('[' + cmd[i + 1]  + ']')
                    return eval('[' + cmd[0] + ']')
                
                list_4d = ndlist((2, 3, 4))
                list_3d_int = ndlist((2, 3, 4), dtype=int)
                
                print list_4d
                print list_3d_int
                

                结果:

                [[[[], [], [], []], [[], [], [], []], [[], [], [], []]], [[[], [], [], []], [[], [], [], []], [[], [], [], []]]]
                [[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]]
                

                【讨论】:

                  【解决方案11】:

                  您还可以使用 append 方法构建具有不同长度行的二维列表。 例如

                  sf_gcov_cell = []
                  sf_gcov_cell.append(['r1_c1', 'r2_c2_', 'r3_c3__', 'r4_c4'])
                  sf_gcov_cell.append(['r2_c1', 'r2_c2'])
                  sf_gcov_cell.append(['r3_c1', 'r3_c2___', 'r3_c3_'])
                  print(sf_gcov_cell)
                  

                  结果:

                  [['r1_c1', 'r2_c2_', 'r3_c3__', 'r4_c4'], ['r2_c1', 'r2_c2'], ['r3_c1', 'r3_c2___', 'r3_c3_']]
                  

                  【讨论】:

                    【解决方案12】:

                    只需使用一个简单的递归函数,它会不断地将新数组附加到自身初始化的数组中。

                    #  Counts the maximum amount of dimensions in an array
                    def dcounter(array: list, total = 1):
                    
                        for arr in array:
                            return dcounter(arr, total + 1)
                    
                        return total
                    
                    
                    #  Create array with specified amount of dimensions
                    def nd_array(dimensions = 1, array = list(), i = 0):
                    
                        if dimensions > 1:
                            array.append([])
                            nd_array(dimensions - 1, array[i])
                            
                        return array
                    
                    
                    #  Create a 5D array
                    array = nd_array(5)
                    print(array) #  =>  "[[[[[]]]]]"
                    
                    
                    #  Get the maximum amount of dimensions in the array
                    amount = dcounter(array)
                    print(amount) #  =>  "5"
                    

                    如果你想指定每个维度的大小,每个维度内的数组数量,那么你可以修改nd_array 来这样做。

                    【讨论】:

                      【解决方案13】:

                      这是一个适用于任意数量维度的 losution:

                      def multi_dimensional_list(dimensions, filling=None):
                          if len(dimensions) == 1:
                              return [filling] * dimensions[0]
                          else:
                              return [
                                  multi_dimensional_list(dimensions[1:], filling)
                                  for _ in range(dimensions[0])
                              ]
                      
                      
                      print(multi_dimensional_list([2, 3, 4], 0))
                      """
                          output :
                          [
                              [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],
                              [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
                          ]
                      """
                      

                      【讨论】:

                        猜你喜欢
                        • 2016-05-27
                        • 2017-02-19
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2018-07-24
                        • 1970-01-01
                        • 1970-01-01
                        • 2018-04-17
                        相关资源
                        最近更新 更多