Alasdair
Alasdair

Reputation: 308909

Creating lists of lists in a pythonic way

I'm using a list of lists to store a matrix in python. I tried to initialise a 2x3 Zero matrix as follows.

mat=[[0]*2]*3

However, when I change the value of one of the items in the matrix, it changes the value of that entry in every row, since the id of each row in mat is the same. For example, after assigning

mat[0][0]=1

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

I know I can create the Zero matrix using a loop as follows,

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

but can anyone show me a more pythonic way?

Upvotes: 11

Views: 1464

Answers (8)

RemcoGerlich
RemcoGerlich

Reputation: 31260

If the sizes involved are really only 2 and 3,

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

is easily best and hasn't been mentioned yet.

Upvotes: 2

John La Rooy
John La Rooy

Reputation: 304205

This one is faster than the accepted answer!
Using xrange(rows) instead of [0]*rows makes no difference.

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

A variation that doesn't use itertools and runs around the same speed

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

From 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

Upvotes: 7

John La Rooy
John La Rooy

Reputation: 304205

Is there anything itertools can't do? :)

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

Upvotes: 1

miku
miku

Reputation: 188054

What about:

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; from the 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.

Upvotes: 2

othercriteria
othercriteria

Reputation: 441

I use

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

although depending on what you do with the matrix after you create it, you might take a look at using a NumPy array.

Upvotes: 4

Ben Blank
Ben Blank

Reputation: 56572

Use a list comprehension:

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

Or, as a function:

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

Upvotes: 9

Nadia Alramli
Nadia Alramli

Reputation: 114943

This will work

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

Upvotes: 3

Paolo Bergantino
Paolo Bergantino

Reputation: 488434

Try this:

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

This is also discussed 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]]

Upvotes: 8

Related Questions