如何在Python中初始化二维数组?

the*_*ace 243 python multidimensional-array

我正在开始python,我正在尝试使用二维列表,我最初在每个地方填充相同的变量.我想出了这个:

def initialize_twodlist(foo):
    twod_list = []
    new = []
    for i in range (0, 10):
        for j in range (0, 10):
            new.append(foo)
        twod_list.append(new)
        new = []
Run Code Online (Sandbox Code Playgroud)

它给出了期望的结果,但感觉就像一个解决方法.有没有更简单/更短/更优雅的方式来做到这一点?

Mik*_*ham 361

Python中经常出现的模式是

bar = []
for item in some_iterable:
    bar.append(SOME EXPRESSION)
Run Code Online (Sandbox Code Playgroud)

这有助于激发列表推导的引入,将列表转换为

bar = [SOME EXPRESSION for item in some_iterable]
Run Code Online (Sandbox Code Playgroud)

这是更短,有时更清晰.通常你会养成识别这些并经常用理解来代替循环的习惯.

您的代码遵循此模式两次

twod_list = []                                       \                      
for i in range (0, 10):                               \
    new = []                  \ can be replaced        } this too
    for j in range (0, 10):    } with a list          /
        new.append(foo)       / comprehension        /
    twod_list.append(new)                           /
Run Code Online (Sandbox Code Playgroud)

  • +1教授如何钓鱼,而不是给他鱼. (182认同)
  • 顺便说一句,x [x(10)中x的[[foo]*10]可以用来摆脱一种理解.问题是乘法执行浅拷贝,因此new = [foo]*10 new = [new]*10将为您提供包含相同列表十次的列表. (28认同)
  • 类似地,`[foo]*10`是一个具有相同精确`foo`10次的列表,这可能重要也可能不重要. (5认同)
  • 我们可以使用最简单的方法:wtod_list = [[0 for x in xrange(10))] for x in xrange(10)] (2认同)
  • @Scott Wolchok 和 Mike Graham - 非常重要的一点是,将与列表相乘复制对同一列表的引用。如何在不追加的情况下实例化 MxN 矩阵? (2认同)
  • 对于 Mike Graham 对 `[foo] * 10` 的评论:这意味着如果你用随机数填充数组(将 `[random.randint(1,2)] * 10` 评估为 `[ 1] * 10` 或 `[2] * 10` 这意味着你得到一个全 1 或 2 的数组,而不是一个随机数组。 (2认同)

Ada*_*eld 205

您可以使用列表理解:

x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of 'foo' (which can depend on i and j if you want)
Run Code Online (Sandbox Code Playgroud)

  • 这个答案工作正常,但我因为我们为行迭代 `i` 和为列迭代 `j`,我认为最好在你的语法中交换 `i` 和 `j` 以便更好地理解并将范围更改为 2 个不同的数字. (5认同)
  • 因为大小 (10) 是一样的,所以如果不是嵌套循环必须首先出现 [foo for j in range(range_of_j)] for i in range(range_of_i)] (4认同)

Joh*_*ooy 130

这种方式比嵌套列表推导更快

[x[:] for x in [[foo] * 10] * 10]    # for immutable foo!
Run Code Online (Sandbox Code Playgroud)

这里有一些python3时序,适用于小型和大型列表

$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]'
1000000 loops, best of 3: 1.55 usec per loop

$ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]'
100000 loops, best of 3: 6.44 usec per loop

$ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]'
100 loops, best of 3: 5.5 msec per loop

$ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]'
10 loops, best of 3: 27 msec per loop
Run Code Online (Sandbox Code Playgroud)

说明:

[[foo]*10]*10创建重复10次的同一对象的列表.你不能只使用它,因为修改一个元素将修改每一行中的相同元素!

x[:]相当于list(X)但更高效,因为它避免了名称查找.无论哪种方式,它都会创建每行的浅表副本,因此现在所有元素都是独立的.

所有元素都是相同的foo对象,所以如果foo是可变的,你就不能使用这个方案.你必须使用它

import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]
Run Code Online (Sandbox Code Playgroud)

或者假设一个Foo返回foos 的类(或函数)

[[Foo() for x in range(10)] for y in range(10)]
Run Code Online (Sandbox Code Playgroud)

  • @Mike,你是否错过了大胆的部分?如果foo是可变的,那么其他任何答案都不起作用(除非你根本没有改变foo) (4认同)

小智 96

不要使用[[v]*n]*n,这是一个陷阱!

>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
Run Code Online (Sandbox Code Playgroud)

但是t = [[0]*3,范围(3)中的i]很好

  • 是的,我也陷入了这个陷阱.这是因为`*`正在复制对象(列表)的`地址`. (19认同)
  • 赞成,因为这吸引了我。更清楚地说,“[[0] * col for _ in range(row)]”。 (10认同)
  • 这是一个真正的陷阱。我向西行驶了2个小时 (3认同)
  • 找到了为什么第一个维度有效但第二个维度不起作用的答案。列表乘法会产生浅拷贝。当您分配给索引时,它会进行适当的更改,但访问不会,因此当您执行“a[x][y] = 2”时,它是对第 x 个索引进行访问,而不是分配 - 只有第 y 个访问是实际上改变了。此页面帮助我用图表进行解释,这些图表可能比我在此评论中尝试解释的更好:https://www.geeksforgeeks.org/python-using-2d-arrays-lists-the-right-way/ (3认同)
  • 为什么它适用于第一个维度但不适用于第二个维度?`l = [0] * 3` 后面跟着 `l[0] = 1` 就可以得到 `[1, 0, 0]`。 (2认同)

Vip*_*pul 59

要在Python中初始化二维数组:

a = [[0 for x in range(columns)] for y in range(rows)]
Run Code Online (Sandbox Code Playgroud)

  • 要将所有值初始化为0,只需对范围(行)中的y使用`a = [[0表示范围(列)x]]. (4认同)

Ign*_*ams 25

[[foo for x in xrange(10)] for y in xrange(10)]
Run Code Online (Sandbox Code Playgroud)

  • @codemuncher `[[0] * col] * row` 没有做你想要的原因是因为当你以这种方式初始化一个二维列表时,Python 不会创建每一行的不同副本。相反,它将使用指向 `[0]*col` 的相同副本的指针初始化外部列表。您对其中一行所做的任何编辑都将反映在其余行中,因为它们实际上都指向内存中的相同数据。 (3认同)

Tus*_*har 24

对于那些困惑为什么[[\'\']*m]*n不好用的人来说。

\n

Python 使用名为 \xe2\x80\x9cCall by Object Reference\xe2\x80\x9d 或 \xe2\x80\x9cCall by assignment\xe2\x80\x9d 的系统。(更多信息

\n

最好的方法是[[\'\' for i in range(columns)] for j in range(rows)]
\n这将解决所有问题。

\n

如需更多说明
\n示例:

\n
>>> x = [[\'\']*3]*3\n[[\'\', \'\', \'\'], [\'\', \'\', \'\'], [\'\', \'\', \'\']]\n>>> x[0][0] = 1\n>>> print(x)\n[[1, \'\', \'\'], [1, \'\', \'\'], [1, \'\', \'\']]\n
Run Code Online (Sandbox Code Playgroud)\n
>>> y = [[\'\' for i in range(3)] for j in range(3)]\n[[\'\', \'\', \'\'], [\'\', \'\', \'\'], [\'\', \'\', \'\']]\n>>> y[0][0]=1\n>>> print(y)\n[[1, \'\', \'\'], [\'\', \'\', \'\'], [\'\', \'\', \'\']]\n
Run Code Online (Sandbox Code Playgroud)\n


Mik*_*ham 22

通常,当您需要多维数组时,您不需要列表列表,而是需要一个numpy数组或可能是一个dict.

例如,有了numpy,你会做类似的事情

import numpy
a = numpy.empty((10, 10))
a.fill(foo)
Run Code Online (Sandbox Code Playgroud)

  • numpy提供了一个多维数组类型.从列表中构建一个好的多维数组是可能的,但对初学者来说比使用numpy更有用和更难.嵌套列表对于某些应用程序来说非常棒,但通常不会想要2d数组的人最好. (3认同)
  • 虽然"numpy"很棒,但我认为这对初学者来说可能有些过分. (2认同)

hit*_*wen 12

你可以这样做:

[[element] * numcols] * numrows
Run Code Online (Sandbox Code Playgroud)

例如:

>>> [['a'] *3] * 2
[['a', 'a', 'a'], ['a', 'a', 'a']]
Run Code Online (Sandbox Code Playgroud)

但这会产生不良副作用:

>>> b = [['a']*3]*3
>>> b
[['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
>>> b[1][1]
'a'
>>> b[1][1] = 'b'
>>> b
[['a', 'b', 'a'], ['a', 'b', 'a'], ['a', 'b', 'a']]
Run Code Online (Sandbox Code Playgroud)

  • 根据我的经验,这种"不良"效应往往是一些非常糟糕的逻辑错误的根源.在我看来,这种方法应该避免,相反@Vipul的答案要好得多. (11认同)
  • 由于存在意想不到的副作用,您不能真正将其视为矩阵。如果不需要修改内容就可以了。 (2认同)

btk*_*btk 8

如果它是一个人口稀少的数组,你可能最好使用一个用元组键入的字典:

dict = {}
key = (a,b)
dict[key] = value
...
Run Code Online (Sandbox Code Playgroud)


Mou*_*leh 7

twod_list = [[foo for _ in range(m)] for _ in range(n)]
Run Code Online (Sandbox Code Playgroud)

因为n是行数,m是列数,而foo是值。


Abh*_*tia 6

代码:

num_rows, num_cols = 4, 2
initial_val = 0
matrix = [[initial_val] * num_cols for _ in range(num_rows)]
print(matrix) 
# [[0, 0], [0, 0], [0, 0], [0, 0]]
Run Code Online (Sandbox Code Playgroud)

initial_val 必须是不可变的。


小智 5

t = [ [0]*10 for i in [0]*10]
Run Code Online (Sandbox Code Playgroud)

为每个元素[0]*10创建一个新的..