【问题标题】:Creating lists of lists in a pythonic way以pythonic方式创建列表列表
【发布时间】:2010-10-29 17:11:14
【问题描述】:

我正在使用列表列表在 python 中存储矩阵。我尝试如下初始化一个 2x3 零矩阵。

mat=[[0]*2]*3

但是,当我更改矩阵中一项的值时,它会更改 每一 行中该条目的值,因为 mat 中每一行的 id 是相同的.比如赋值后

mat[0][0]=1

mat[[1, 0], [1, 0], [1, 0]]

我知道我可以使用如下循环创建零矩阵,

mat=[[0]*2]
for i in range(1,3):
    mat.append([0]*2)

但是谁能告诉我一个更 Pythonic 的方式?

【问题讨论】:

  • 应该有一种——最好只有一种——明显的方法。 ;-)

标签: list matrix python


【解决方案1】:

试试这个:

>>> cols = 6
>>> rows = 3
>>> a = [[0]*cols for _ in [0]*rows]
>>> a
[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
>>> a[0][3] = 2
>>> a
[[0, 0, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]

这也在讨论in this answer

>>> lst_2d = [[0] * 3 for i in xrange(3)]
>>> lst_2d
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> lst_2d[0][0] = 5
>>> lst_2d
[[5, 0, 0], [0, 0, 0], [0, 0, 0]]

【讨论】:

  • 谢谢,这就是我要找的!
  • +1 - 好东西。我只是在学习 Python,所以我非常感谢看到“pythonic”代码的 sn-ps。
  • "[0]*rows" 部分具有误导性;您正在创建一个列表,除了它的长度之外,它不会以任何方式使用。使用xrange(n) 或(不太可能)itertools.repeat(None, n) 在 Python 中执行 n 次。
【解决方案2】:

这会起作用

col = 2
row = 3
[[0] * col for row in xrange(row)]

【讨论】:

    【解决方案3】:

    怎么样:

    m, n = 2, 3
    >>> A = [[0]*m for _ in range(n)]
    >>> A
    [[0, 0], [0, 0], [0, 0]]
    >>> A[0][0] = 1
    [[1, 0], [0, 0], [0, 0]]
    

    又名列表理解;来自docs

    List comprehensions provide a concise way to create lists 
    without resorting to use of     
    map(), filter() and/or lambda. 
    The resulting list definition tends often to be clearer    
    than lists built using those constructs.
    

    【讨论】:

      【解决方案4】:

      使用list comprehension

      >>> mat = [[0]*2 for x in xrange(3)]
      >>> mat[0][0] = 1
      >>> mat
      [[1, 0], [0, 0], [0, 0]]
      

      或者,作为一个函数:

      def matrix(rows, cols):
          return [[0]*cols for x in xrange(rows)]
      

      【讨论】:

        【解决方案5】:

        我用

        mat = [[0 for col in range(3)] for row in range(2)]
        

        虽然取决于您在创建矩阵后对矩阵所做的操作,但您可能会考虑使用 NumPy 数组。

        【讨论】:

        • 我将在某个时候探索 NumPy,但对于我目前的问题,列表列表就足够了。
        【解决方案6】:

        有什么是 itertools 不能做的吗? :)

        >>> from itertools import repeat,izip
        >>> rows=3
        >>> cols=6
        >>> A=map(list,izip(*[repeat(0,rows*cols)]*cols))
        >>> A
        [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
        >>> A[0][3] = 2
        >>> A
        [[0, 0, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
        

        【讨论】:

          【解决方案7】:

          这个比公认的答案更快!
          使用 xrange(rows) 而不是 [0]*rows 没有区别。

          >>> from itertools import repeat
          >>> rows,cols = 3,6
          >>> a=[x[:] for x in repeat([0]*cols,rows)]
          

          不使用 itertools 并且运行速度相同的变体

          >>> a=[x[:] for x in [[0]*cols]*rows]
          

          来自 ipython:

          In [1]: from itertools import repeat
          
          In [2]: rows=cols=10
          
          In [3]: timeit a = [[0]*cols for _ in [0]*rows]
          10000 loops, best of 3: 17.8 us per loop
          
          In [4]: timeit a=[x[:] for x in repeat([0]*cols,rows)]
          100000 loops, best of 3: 12.7 us per loop
          
          In [5]: rows=cols=100
          
          In [6]: timeit a = [[0]*cols for _ in [0]*rows]
          1000 loops, best of 3: 368 us per loop
          
          In [7]: timeit a=[x[:] for x in repeat([0]*cols,rows)]
          1000 loops, best of 3: 311 us per loop
          

          【讨论】:

            【解决方案8】:

            如果涉及的尺寸真的只有2和3,

            mat = [[0, 0], [0, 0], [0, 0]]
            

            是最好的,还没有被提及。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-02-26
              • 1970-01-01
              • 1970-01-01
              • 2011-04-23
              • 1970-01-01
              • 1970-01-01
              • 2019-09-03
              • 2022-12-22
              相关资源
              最近更新 更多