2009-05-28 2 views
10

Я использую список списков для хранения матрицы в python. Я попытался инициализировать матрицу нулевого размера 2x3 следующим образом.Создание списков списков в pythonic способом

mat=[[0]*2]*3 

Однако, когда я изменить значение одного из элементов в матрице, он изменяет значение этой записи в каждый строки, так как идентификатор каждой строки в mat одно и то же. Например, после присвоения

mat[0][0]=1 

mat является [[1, 0], [1, 0], [1, 0]].

Я знаю, что могу создать нулевую матрицу, используя петлю следующим образом,

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

, но может кто-нибудь показать мне более вещий путь?

+0

Должен быть один - и желательно только один - простой способ сделать это. ;-) – Ubiquitous

ответ

9

Использовать list comprehension:

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

Или, как функция:

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

Попробуйте это:

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

Это также обсуждается 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

Спасибо, вот что я искал! – Alasdair

+0

+1 - хороший материал. Я просто изучаю Python, поэтому я очень благодарен за просмотр фрагментов кода «pythonic». – duffymo

+7

"' [0] * rows' "часть вводит в заблуждение; вы создаете список, который не используется каким-либо образом, кроме его длины. Используйте либо «xrange (n)», либо (менее вероятно) 'itertools.repeat (None, n)', чтобы что-то делать в Python 'n' раз. – jfs

3

Это будет работать

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

насчет:

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; от 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

я использую

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

хотя в зависимости от того, что вы делаете с матрицы после его создания, вы можете взглянуть на использование массива NumPy.

+0

В какой-то момент я собираюсь исследовать NumPy, но для моей текущей проблемы достаточно списка списков. – Alasdair

1

См. Также this question для обобщения на n-уровне вложенного списка/n-мерную матрицу.

1

Есть ли что-нибудь, что он не может сделать? :)

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

Этот вариант быстрее, чем принятый ответ!
Использование xrange (rows) вместо [0] * строк не имеет значения.

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

Разновидность, которая не использует itertools и работает примерно с той же скоростью

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

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

Если размеры участвующих действительно только 2 и 3,

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

легко лучший и hasn еще не упоминалось.

Смежные вопросы