如何在Python中定义二维数组


723

我想定义一个没有初始化长度的二维数组,如下所示:

Matrix = [][]

但这不起作用...

我已经尝试过下面的代码,但是它也是错误的:

Matrix = [5][5]

错误:

Traceback ...

IndexError: list index out of range

我怎么了


14
没有定义数组或其他任何东西。但是,您可以创建多维序列,如此处的答案所示。请记住,python 变量是无类型的,但是强类型的。
SingleNegationElimination

1
我糊涂了。来自其他语言:它是包含1D数组的1D数组和2D数组之间的区别。而且AFAIK无法在python中具有多维数组(或列表)。应该在这里说...
Dirk Reichel

Answers:


1008

从技术上讲,您正在尝试索引未初始化的数组。您必须先使用列表初始化外部列表,然后再添加项目。Python将其称为“列表理解”。

# Creates a list containing 5 lists, each of 8 items, all set to 0
w, h = 8, 5;
Matrix = [[0 for x in range(w)] for y in range(h)] 

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

Matrix[0][0] = 1
Matrix[6][0] = 3 # error! range... 
Matrix[0][6] = 3 # valid

请注意,矩阵是“ y”地址主地址,换句话说,“ y索引”位于“ x索引”之前。

print Matrix[0][0] # prints 1
x, y = 0, 6 
print Matrix[x][y] # prints 3; be careful with indexing! 

尽管您可以根据需要命名它们,但是如果您对内部列表和外部列表都使用“ x”,并且希望使用非平方矩阵,那么我会以这种方式来避免索引可能引起的混淆。


219
[[x表示范围内的x(cols_count),0表示范围内的x(rows_count)]]
songhir 2014年

3
奇怪的是ademar111190。在Python 3中没有xrange,但如果您必须使用Python 2,那么如果您不想不必要地创建对象,则使用xrange是正确的函数。
戴夫

4
@dave如果不需要零填充,可以使用它range直接创建内部列表:[range(5) for x in range(5)]
alanjds 2015年

2
@alanjds-是的,但是您仍然可以在Python 2中为外部迭代创建许多不必要的对象引用(尝试使用非常大的范围)。同样,初始化为某个值几乎总是您想要的-通常不为0。range产生一个可迭代的集合-xrange返回一个生成器。我的意思是,阿德玛“纠正”了实际上比他的纠正更正确和有效的东西。
戴夫2015年

10
@ 6packkid该[0] * w部分很好,但是[[0] * w] * h]会产生意外的行为。尝试mat = [[0] * 3] * 3; mat[0][1] = 10; print(mat == [[0, 10, 0], [0, 10, 0], [0, 10, 0]])mat = [[0] * 3 for i in range(3)]; mat[0][1] = 10; print(mat == [[0, 10, 0], [0, 0, 0], [0, 0, 0]])
senderle'7

406

如果您确实需要矩阵,最好使用numpy。在numpy大多数情况下,矩阵运算使用具有二维的数组类型。有很多方法可以创建一个新数组。最有用的zeros函数之一是函数,它采用shape参数并返回给定形状的数组,其值初始化为零:

>>> import numpy
>>> numpy.zeros((5, 5))
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

这是创建二维数组和矩阵的其他一些方法(为了紧凑起见,删除了输出):

numpy.arange(25).reshape((5, 5))         # create a 1-d range and reshape
numpy.array(range(25)).reshape((5, 5))   # pass a Python range and reshape
numpy.array([5] * 25).reshape((5, 5))    # pass a Python list and reshape
numpy.empty((5, 5))                      # allocate, but don't initialize
numpy.ones((5, 5))                       # initialize with ones

numpy也提供了一种matrix类型,但是不再建议将其用于任何用途,以后可能会删除numpy它。


78
每当需要矩阵时,都想使用numpy。这个答案应该是第一个。
Pat B

2
问题使用英语单词“ matrix”的事实并不意味着他们应该使用np.matrix它来表示它。用numpy表示矩阵的正确方法是使用array
user2357112支持Monica's

@ user2357112,正如您所看到的,上面列出的大多数示例都输出arrays而不是矩阵。尽管并不总是鼓励这样做,但是使用matrix上下文有合理的理由。
senderle

1
@senderle,可以扩展使用理由matrix吗?自从@引入operator以来,自写这篇文章以来似乎没有什么理由了。
jpp

1
正如帖子先前所说,@ jpp,来自matlab的人们可能会发现它很有用。但是numpy文档现在表明该类可能会在以后被弃用并删除,因此我将其排除在答案之外。
senderle

337

这是用于初始化列表列表的简短表示法:

matrix = [[0]*5 for i in range(5)]

不幸的是,将其缩短为类似的方法5*[5*[0]]实际上是行不通的,因为最终您会得到同一列表的5个副本,因此,当您修改其中一个副本时,它们都会更改,例如:

>>> matrix = 5*[5*[0]]
>>> matrix
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> matrix[4][4] = 2
>>> matrix
[[0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2]]

4
您能否解释“缩短”失败背后的逻辑?为什么在这种情况下python为什么输出相同列表的副本,而在情况下为什么输出不同单元格的数组[0]*5
mike622867 2015年

12
上面的注释并不完全正确:[0] * 5仍然创建一个具有5倍引用同一对象的序列,该对象表示数字0。但是您永远不会注意到这一点,因为0是不可变的(我想说0的行为就像一个值-或您可能将其视为原始数据类型-因为它是不可变的,因此您对引用相同的对象而不是复制都不会遇到问题。)
dreua,

4
更Python:[[0]*5 for _ in range(5)]匿名循环计数器你不使用
让·弗朗索瓦·法布尔

很高兴您在第二个示例中指出了浅拷贝的问题。
whatacold

谢谢@dreua,我真的很困惑如何[0]*5正常工作。现在我明白了为什么[{0}]*8这也是一个坏主意。
裤裤

110

如果要创建一个空矩阵,则正确的语法是

matrix = [[]]

如果您要生成大小为5的矩阵,并用0填充,

matrix = [[0 for i in xrange(5)] for i in xrange(5)]

@KorayTugay因为矩阵是使用嵌套在另一个列表(列)中的Python列表(行)表示的。
elig

2
对于Python-3使用范围函数来代替x范围FUNC
勒凯什乔杜里

76

如果只需要一个二维容器来容纳某些元素,则可以方便地使用字典:

Matrix = {}

然后,您可以执行以下操作:

Matrix[1,2] = 15
print Matrix[1,2]

这是有效的,因为它1,2是一个元组,并且您将其用作索引字典的键。结果类似于哑的稀疏矩阵。

如osa和Josap Valls所指出的,您也可以使用,Matrix = collections.defaultdict(lambda:0)以便丢失的元素具有默认值0

Vatsal进一步指出,该方法对于大型矩阵可能不是很有效,并且仅应在代码的非关键性能部分中使用。


2
然后,您也可以执行import collections; Matrix = collections.defaultdict(float),用零代替未初始化的元素。
osa

2
不能访问元组(1,2)的字典作为键具有最坏情况下的O(n)复杂度。在内部,它将对元组进行哈希处理。而使用2D数组将给O(1)时间复杂度以访问索引[1,2] access。因此,为此使用dict并不是一个好的选择。
Vatsal

@Vatsal wiki.python.org/moin/TimeComplexity说平均情况是O(1),但最糟糕的情况是正确的。无论如何,除非您在谈论很多项目,否则您不会在意这种差异。实际上,我将比起访问时间更担心内存。
enobayram

同样,在算法的总体复杂度等于或大于O(n ^ 2)之前,我们始终尝试避免使用dict。作为n次,O(n)次访问将带来O(n ^ 2)复杂度。
Vatsal

@enobayram,对不起,但我不同意。如果最坏的情况是O(n)次访问被执行了'n'次,则渐进分析将始终给出O(n ^ 2)。摊销分析可以提供较小的范围。摊销和平均情况之间存在巨大差异……在做出任何假设和模糊评论之前,请先参阅
Vatsal 2015年

42

在Python中,您将创建一个列表列表。您不必提前声明尺寸,但是可以声明。例如:

matrix = []
matrix.append([])
matrix.append([])
matrix[0].append(2)
matrix[1].append(3)

现在,matrix [0] [0] == 2和matrix [1] [0] ==3。您还可以使用列表理解语法。此示例两次使用它来构建“二维列表”:

from itertools import count, takewhile
matrix = [[i for i in takewhile(lambda j: j < (k+1) * 10, count(k*10))] for k in range(10)]

6
extend在第一种情况下也会有帮助:如果您以开头m = [[]],则可以使用添加到内部列表(扩展行)m[0].extend([1,2]),并使用添加到外部列表(添加新行)m.append([3,4]),这些操作将使您离开[[1, 2], [3, 4]]
askewchan

22

公认的答案是正确且正确的,但是花了我一段时间才了解到我也可以使用它来创建一个完全空的数组。

l =  [[] for _ in range(3)]

结果是

[[], [], []]

22

您应该列出列表,最好的方法是使用嵌套的理解:

>>> matrix = [[0 for i in range(5)] for j in range(5)]
>>> pprint.pprint(matrix)
[[0, 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][5]示例中,您正在创建一个内部带有整数“ 5”的列表,并尝试访问其第五项,这自然会引发IndexError,因为没有第五项:

>>> l = [5]
>>> l[5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

实际上,row_index('i')和column_index('j')的顺序如下:'>>>矩阵= [[0对于range(5)的column_index为0]对于range(5)的row_index为]“
Aniruddha Kalburgi

22
rows = int(input())
cols = int(input())

matrix = []
for i in range(rows):
  row = []
  for j in range(cols):
    row.append(0)
  matrix.append(row)

print(matrix)

为什么这么长的代码,Python您也会问?

很久以前,当我不熟悉Python时,我看到了编写2D矩阵的单行答案,并告诉自己我不再打算在Python中再次使用2D矩阵。(这些行很吓人,它没有给我有关Python所做的任何信息。还要注意,我不知道这些速记法。)

无论如何,这是一个来自C,CPP和Java背景的初学者的代码

给Python爱好者和专家的说明:请不要因为我编写了详细的代码而投了反对票。


13

重写以便于阅读:

# 2D array/ matrix

# 5 rows, 5 cols
rows_count = 5
cols_count = 5

# create
#     creation looks reverse
#     create an array of "cols_count" cols, for each of the "rows_count" rows
#        all elements are initialized to 0
two_d_array = [[0 for j in range(cols_count)] for i in range(rows_count)]

# index is from 0 to 4
#     for both rows & cols
#     since 5 rows, 5 cols

# use
two_d_array[0][0] = 1
print two_d_array[0][0]  # prints 1   # 1st row, 1st col (top-left element of matrix)

two_d_array[1][0] = 2
print two_d_array[1][0]  # prints 2   # 2nd row, 1st col

two_d_array[1][4] = 3
print two_d_array[1][4]  # prints 3   # 2nd row, last col

two_d_array[4][4] = 4
print two_d_array[4][4]  # prints 4   # last row, last col (right, bottom element of matrix)

13

采用:

matrix = [[0]*5 for i in range(5)]

第一维的* 5起作用是因为在此级别上,数据是不可变的。


5
我可能会这样写:matrix = [[0]*cols for _ in range(rows)]
Shital Shah,

12

声明零(一)矩阵:

numpy.zeros((x, y))

例如

>>> numpy.zeros((3, 5))
    array([[ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.]])

或numpy.ones((x,y))例如

>>> np.ones((3, 5))
array([[ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.]])

甚至三个尺寸都是可能的。(http://www.astro.ufl.edu/~warner/prog/python.html参见->多维数组)


12

这就是我通常在python中创建2D数组的方式。

col = 3
row = 4
array = [[0] * col for _ in range(row)]

与在列表理解中使用两个for循环相比,我发现此语法易于记住。


11

我正在使用我的第一个Python脚本,我对方矩阵示例有些困惑,因此希望以下示例可以帮助您节省一些时间:

 # Creates a 2 x 5 matrix
 Matrix = [[0 for y in xrange(5)] for x in xrange(2)]

以便

Matrix[1][4] = 2 # Valid
Matrix[4][1] = 3 # IndexError: list index out of range


7

我读了这样的逗号分隔文件:

data=[]
for l in infile:
    l = split(',')
    data.append(l)

然后,列表“数据”是带有索引数据的列表的列表[行] [列]


7

如果您希望能够将其视为2D数组,而不是被迫以列表列表的方式思考(我认为这自然得多),则可以执行以下操作:

import numpy
Nx=3; Ny=4
my2Dlist= numpy.zeros((Nx,Ny)).tolist()

结果是一个列表(不是NumPy数组),您可以用数字,字符串或其他内容覆盖各个位置。


numpy.matrix相当于numpy.zeros无零而不列表?
莫妮卡(Monica)'18年

6

这就是字典的用途!

matrix = {}

您可以通过两种方式定义

matrix[0,0] = value

要么

matrix = { (0,0)  : value }

结果:

   [ value,  value,  value,  value,  value],
   [ value,  value,  value,  value,  value],
   ...

6

采用:

import copy

def ndlist(*args, init=0):
    dp = init
    for x in reversed(args):
        dp = [copy.deepcopy(dp) for _ in range(x)]
    return dp

l = ndlist(1,2,3,4) # 4 dimensional list initialized with 0's
l[0][1][2][3] = 1

我确实认为NumPy是要走的路。如果您不想使用NumPy,则以上是一种通用方法。


我喜欢用香草Python做一些简单的事情而不必使用numpy的尝试。
里克·亨德森

4

通过使用列表:

matrix_in_python  = [['Roy',80,75,85,90,95],['John',75,80,75,85,100],['Dave',80,80,80,90,95]]

通过使用dict:您还可以将此信息存储在哈希表中,以进行快速搜索,例如

matrix = { '1':[0,0] , '2':[0,1],'3':[0,2],'4' : [1,0],'5':[1,1],'6':[1,2],'7':[2,0],'8':[2,1],'9':[2,2]};

matrix ['1']将为您提供O(1)时间的结果

* nb:您需要处理哈希表中的冲突


4

如果在开始之前没有尺寸信息,请创建两个一维列表。

list 1: To store rows
list 2: Actual two-dimensional matrix

将整个行存储在第一个列表中。完成后,将列表1附加到列表2:

from random import randint

coordinates=[]
temp=[]
points=int(raw_input("Enter No Of Coordinates >"))
for i in range(0,points):
    randomx=randint(0,1000)
    randomy=randint(0,1000)
    temp=[]
    temp.append(randomx)
    temp.append(randomy)
    coordinates.append(temp)

print coordinates

输出:

Enter No Of Coordinates >4
[[522, 96], [378, 276], [349, 741], [238, 439]]

3
# Creates a list containing 5 lists initialized to 0
Matrix = [[0]*5]*5

请注意此简短表达,请参见@FJ答案中的完整解释


19
以这种方式要小心,因为Matrix[0], Matrix[1], ..., Matrix[4]所有都指向同一个数组,所以之后Matrix[0][0] = 3,您将期望Matrix[0][0] == Matrix[1][0] == ... == Matrix[4][0] == 3
gongzhitaao 2014年

1
感谢恭子zh的评论。如果我读得更早,它至少可以为我节省半小时。.如果矩阵中的每一行都指向内存中的同一位置,似乎没有什么用处,并且如果您不知道自己在做什么甚至很危险!我很确定这不是问这个问题的Masoud Abasian想要做的。
阿德里安

7
您应该删除此答案,因为它不是正确的答案。初学者可能会感到困惑。
cxxl

2
您指的是什么答案?我没有看到名称为“ FJ”的用户(甚至在删除的答案中也没有)。
彼得·莫滕森

3
l=[[0]*(L) for _ in range(W)]

将比:

l = [[0 for x in range(L)] for y in range(W)] 

2
重复的答案之一已经在下面回答。也[[0]*(L) for i in range(W)]应该是[[0]*(L) for _ in range(W)]因为i没有在任何地方使用
Ayush Vatsyayan

2

您可以通过将两个或多个方括号或第三个方括号([]用逗号分隔)嵌套在一起来创建一个空的二维列表,如下所示:

Matrix = [[], []]

现在假设您要在Matrix[0][0]其后附加1,然后键入:

Matrix[0].append(1)

现在,键入Matrix并按Enter。输出将是:

[[1], []]


1

如果您需要带有预定义数字的矩阵,则可以使用以下代码:

def matrix(rows, cols, start=0):
    return [[c + start + r * cols for c in range(cols)] for r in range(rows)]


assert matrix(2, 3, 1) == [[1, 2, 3], [4, 5, 6]]

1

这是在python中创建矩阵的代码片段:

# get the input rows and cols
rows = int(input("rows : "))
cols = int(input("Cols : "))

# initialize the list
l=[[0]*cols for i in range(rows)]

# fill some random values in it
for i in range(0,rows):
    for j in range(0,cols):
        l[i][j] = i+j

# print the list
for i in range(0,rows):
    print()
    for j in range(0,cols):
        print(l[i][j],end=" ")

如果我错过了什么,请提出建议。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.