2009-05-28 14 views
10

Estoy usando una lista de listas para almacenar una matriz en python. Intenté inicializar una matriz Cero 2x3 de la siguiente manera.Crear listas de listas de manera pitónica

mat=[[0]*2]*3 

Sin embargo, cuando cambio el valor de uno de los elementos de la matriz, se cambia el valor de esa entrada en cada fila, ya que la ID de cada fila en mat es el mismo. Por ejemplo, después de asignar

mat[0][0]=1 

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

sé que puedo crear la matriz de cero utilizando un bucle de la siguiente manera,

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

pero ¿alguien puede mostrar de una manera más Pythonic?

+0

Debería haber una, y preferiblemente solo una, forma obvia de hacerlo. ;-) – Ubiquitous

Respuesta

9

Utilice un list comprehension:

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

O, como una función:

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

Prueba esto:

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

Esto también se discute 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

¡Gracias, eso es lo que estaba buscando! – Alasdair

+0

+1 - cosas agradables. Solo estoy aprendiendo Python, por lo que agradezco mucho los fragmentos de código "pythonic". – duffymo

+7

"' [0] * rows' "es engañosa; estás creando una lista que no se usa de ninguna manera, excepto su longitud. Utilice '' xrange (n) 'o (menos probable)' itertools.repeat (None, n) 'para hacer algo' n' veces en Python. – jfs

3

Esto funcionará

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

¿Qué hay de:

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 Comprensión de la lista; Del 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

utilizo

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

aunque dependiendo de lo que haces con el matriz después de crearla, puede echarle un vistazo usando una matriz NumPy.

+0

Voy a explorar NumPy en algún momento, pero para mi problema actual, una lista de lista es suficiente. – Alasdair

1

Véase también this question para la generalización a una matriz anidada de n-levels/n-dimensional.

1

¿Hay algo que las herramientas iterativas no puedan hacer? :)

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

¡Éste es más rápido que la respuesta aceptada!
Usar xrange (filas) en lugar de [0] * filas no hace diferencia.

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

Una variación que no utiliza itertools y corre alrededor de la misma velocidad

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

De 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

Si los tamaños implicados son realmente sólo 2 y 3,

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

es fácilmente mejor y hasn No se ha mencionado aún.

Cuestiones relacionadas