2009-05-28 43 views
10

Tôi đang sử dụng danh sách các danh sách để lưu trữ ma trận trong python. Tôi đã cố gắng khởi tạo một ma trận Zero 2x3 như sau.Tạo danh sách các danh sách theo cách pythonic

mat=[[0]*2]*3 

Tuy nhiên, khi tôi thay đổi giá trị của một trong những mặt hàng trong ma trận, nó thay đổi giá trị của mục nhập trong mỗi liên tiếp, kể từ id của mỗi hàng trong mat là như nhau. Ví dụ: sau khi chỉ định

mat[0][0]=1 

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

Tôi biết tôi có thể tạo ra các ma trận Zero, sử dụng một vòng lặp như sau,

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

nhưng bất cứ ai có thể cho tôi một cách pythonic hơn?

+0

Nên có một-- và tốt nhất là chỉ có một - cách rõ ràng để thực hiện điều đó. ;-) – Ubiquitous

Trả lời

9

Sử dụng một list comprehension:

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

Hoặc, như một hàm:

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

Hãy thử điều này:

>>> 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]] 

Đây cũng là thảo luận 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]] 
+0

Cảm ơn, đó là những gì tôi đang tìm kiếm! – Alasdair

+0

+1 - nội dung hay. Tôi chỉ học Python, vì vậy tôi rất cảm kích khi thấy các đoạn mã "pythonic". – duffymo

+7

"' [0] * hàng' "một phần là gây hiểu nhầm; bạn đang tạo danh sách không được sử dụng theo bất kỳ cách nào ngoại trừ độ dài của danh sách. Sử dụng 'xrange (n)' hoặc (ít có khả năng) 'itertools.repeat (None, n)' để làm điều gì đó 'n' lần trong Python. – jfs

3

này sẽ làm việc

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

gì về:

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]] 

Aka List comprehension; từ 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

tôi sử dụng

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

mặc dù phụ thuộc vào những gì bạn làm với ma trận sau khi bạn tạo nó, bạn có thể xem xét sử dụng một mảng NumPy.

+0

Tôi sẽ khám phá NumPy tại một số thời điểm, nhưng đối với vấn đề hiện tại của tôi, danh sách danh sách là đủ. – Alasdair

1

Xem thêm this question để khái quát hóa với ma trận n danh sách lồng nhau/n-chiều.

1

Có điều gì mà công cụ không thể thực hiện? :)

>>> 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]] 
6

Cái này nhanh hơn câu trả lời được chấp nhận!
Sử dụng xrange (hàng) thay vì [0] * hàng không có sự khác biệt.

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

Một biến thể mà không sử dụng itertools và chạy xung quanh cùng một tốc độ

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

Từ 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 
2

Nếu các kích thước liên quan là thực sự chỉ có 2 và 3,

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

dễ dàng nhất và chưa có Chưa được đề cập.

Các vấn đề liên quan