2009-05-28 14 views
10

Sto utilizzando un elenco di elenchi per memorizzare una matrice in python. Ho provato a inizializzare una matrice Zero3 2x3 come segue.Creazione di elenchi di elenchi in modo pironico

mat=[[0]*2]*3 

Tuttavia, quando cambio il valore di uno degli elementi della matrice, cambia il valore di tale voce nel ogni fila, poiché l'id di ciascuna riga mat è lo stesso. Ad esempio, dopo l'assegnazione

mat[0][0]=1 

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

so di poter creare la matrice zero utilizzando un ciclo come segue,

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

ma qualcuno mi può mostrare un modo più divinatorio?

+0

Ci dovrebbe essere uno - e preferibilmente solo un modo - ovvio per farlo. ;-) – Ubiquitous

risposta

9

Utilizzare un list comprehension:

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

Oppure, in funzione:

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

Prova questo:

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

Questo è anche discusso 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

Grazie, questo è quello che stavo cercando! – Alasdair

+0

+1 - roba buona. Sto solo imparando Python, quindi apprezzo molto la visione di frammenti di codice "pythonic". – duffymo

+7

"La parte' [0] * rows' "è fuorviante; stai creando un elenco che non viene utilizzato in alcun modo tranne la sua lunghezza. Usa 'xrange (n)' o (meno probabile) 'itertools.repeat (None, n)' per fare qualcosa 'n' volte in Python. – jfs

3

Ciò funzionerà

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

Che dire:

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

Io uso

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

anche se a seconda di ciò che fai con il matrice dopo averla creata, si potrebbe dare un'occhiata all'utilizzo di un array NumPy.

+0

Ho intenzione di esplorare NumPy ad un certo punto, ma per il mio problema attuale, una lista di elenchi è sufficiente. – Alasdair

1

Vedere anche this question per la generalizzazione a una lista nidificata n livelli/matrice n-dimensionale.

1

C'è qualcosa che gli itertools non possono fare? :)

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

Questo è più veloce della risposta accettata!
L'uso di xrange (righe) invece di [0] * righe non fa differenza.

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

Una variazione che non utilizza itertools e corre intorno alla stessa velocità

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

Da 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

Se le dimensioni in gioco sono davvero solo 2 e 3,

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

è facilmente migliore e hasn stato menzionato ancora

Problemi correlati