2009-05-28 11 views
10

Używam listy list do przechowywania macierzy w python. Próbowałem zainicjować matrycę 2x3 Zero w następujący sposób.Tworzenie list list w pythonic sposób

mat=[[0]*2]*3 

Jednak, kiedy zmienić wartość jednego z elementów w matrycy, zmienia wartość tego wpisu każdy rzędu, ponieważ identyfikator każdego wiersza w mat jest taka sama. Na przykład, po przypisaniu

mat[0][0]=1 

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

wiem, że mogę stworzyć macierz zerową za pomocą pętli w następujący sposób

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

ale ktoś może mi pokazać więcej pythonic sposób?

+0

Powinien istnieć jeden - a najlepiej tylko jeden - czysty sposób na zrobienie tego. ;-) – Ubiquitous

Odpowiedz

9

Użyj list comprehension:

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

Albo, jako funkcja:

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

Spróbuj tego:

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

Jest to również omówione 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

Dzięki, tego właśnie szukałem! – Alasdair

+0

+1 - fajne rzeczy. Po prostu uczę się Pythona, więc bardzo doceniam oglądanie fragmentów "pythonic" kodu. – duffymo

+7

Fragment "' [0] * rows' "wprowadza w błąd; tworzysz listę, która nie jest w żaden sposób używana z wyjątkiem jej długości. Użyj '' xrange (n) 'lub (mniej prawdopodobne)' itertools.repeat (None, n) 'aby coś zrobić' n' razy w Pythonie. – jfs

3

To zadziała

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

Co o:

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

Zrozumienie listy Aka; z 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

używam

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

chociaż w zależności od tego, co robisz z macierz po jej utworzeniu, możesz rzucić okiem na użycie tablicy NumPy.

+0

Mam zamiar zbadać NumPy w pewnym momencie, ale dla mojego obecnego problemu lista list jest wystarczająca. – Alasdair

1

Zobacz także this question dla uogólnienia na n-poziomową listę zagnieżdżoną/macierz n-wymiarową.

1

Czy coś nie może zrobić? :)

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

Ten jest szybszy niż zaakceptowana odpowiedź!
Użycie xrange (wiersze) zamiast [0] * wierszy nie ma znaczenia.

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

Zmienność że nie używa itertools i biega z tą samą prędkością

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

Od 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

Jeśli rozmiary zaangażowane są naprawdę tylko 2 i 3

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

jest z łatwością najlepszy i ma schronienie o których już wspomniano.