Как определить двумерный массив в Python

Я хочу определить двумерный массив без инициализированной длины, как это:

Matrix = [][]

но это не работает...

Я пробовал код ниже, но это тоже неправильно:

Matrix = [5][5]

ошибка:

Traceback ...

IndexError: list index out of range

в чем моя ошибка?

22 ответов


вы технически пытаетесь индексировать неинициализированный массив. Вы должны сначала инициализировать внешний список списками перед добавлением элементов; Python вызывает это "list comprehension".

# Creates a list containing 5 lists, each of 8 items, all set to 0
w, h = 8, 5;
Matrix = [[0 for x in range(w)] for y in range(h)] 

теперь вы можете добавлять элементы в список:

Matrix[0][0] = 1
Matrix[6][0] = 3 # error! range... 
Matrix[0][6] = 3 # valid

print Matrix[0][0] # prints 1
x, y = 0, 6 
print Matrix[x][y] # prints 3; be careful with indexing! 

хотя вы можете назвать их, как хотите, я смотрю на это таким образом, чтобы избежать некоторой путаницы, которая может возникнуть с индексированием, если вы используете "x" для внутреннего и внешнего списков и хотите не квадратную матрицу.


если вы действительно хотите матрицу, вам может быть лучше использовать numpy. Матричные операции в numpy чаще всего использовать тип массива с двумя измерениями. Существует множество способов создания нового массива; одним из наиболее полезных является zeros функция, которая принимает параметр shape и возвращает массив заданной формы со значениями, инициализированными до нуля:

>>> import numpy
>>> numpy.zeros((5, 5))
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

numpy предоставляет matrix типа. Он реже используется, и некоторые люди рекомендую в отношении использовать его. Но это полезно для людей, приходящих в numpy из Matlab и в некоторых других контекстах. Я подумал, что включу его, поскольку мы говорим о матрицах!

>>> numpy.matrix([[1, 2], [3, 4]])
matrix([[1, 2],
        [3, 4]])

вот некоторые другие способы создания 2-d массивов и матриц (с удаленным выходом для компактности):

numpy.matrix('1 2; 3 4')                 # use Matlab-style syntax
numpy.arange(25).reshape((5, 5))         # create a 1-d range and reshape
numpy.array(range(25)).reshape((5, 5))   # pass a Python range and reshape
numpy.array([5] * 25).reshape((5, 5))    # pass a Python list and reshape
numpy.empty((5, 5))                      # allocate, but don't initialize
numpy.ones((5, 5))                       # initialize with ones
numpy.ndarray((5, 5))                    # use the low-level constructor

вот более короткая нотация для инициализации списка списков:

matrix = [[0]*5 for i in range(5)]

к сожалению, сокращая это до чего-то вроде 5*[5*[0]] на самом деле не работает, потому что вы получаете 5 копий одного и того же списка, поэтому при изменении одного из них все они меняются, например:

>>> matrix = 5*[5*[0]]
>>> matrix
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> matrix[4][4] = 2
>>> matrix
[[0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2]]

Если вы хотите создать пустую матрицу, правильный синтаксис

matrix = [[]]

и если вы хотите создать матрицу размера 5, заполненную 0,

matrix = [[0 for i in xrange(5)] for i in xrange(5)]

если все, что вы хотите, это двумерный контейнер для хранения некоторых элементов, вы можете легко использовать вместо словаря:

Matrix = {}

затем вы можете сделать:

Matrix[1,2] = 15
print Matrix[1,2]

это работает, потому что 1,2 - кортеж, и вы используете его в качестве ключа для индексирования словаря. Результат похож на тупую разреженную матрицу.

как указано osa и Josap Valls, вы также можете использовать Matrix = collections.defaultdict(lambda:0) чтобы отсутствующие элементы имели значение по умолчанию 0.

Vatsal далее указывает, что этот метод, вероятно, не очень эффективен для больших матриц и должен использоваться только в не критичных по производительности частях кода.


в Python вы будете создавать список списков. Вам не нужно объявлять измерения заранее, но вы можете. Например:

matrix = []
matrix.append([])
matrix.append([])
matrix[0].append(2)
matrix[1].append(3)

теперь матрица[0][0] == 2 и матрица[1][0] == 3. Можно также использовать синтаксис понимания списка. В этом примере он используется дважды для создания "двумерного списка":

from itertools import count, takewhile
matrix = [[i for i in takewhile(lambda j: j < (k+1) * 10, count(k*10))] for k in range(10)]

принятый ответ хороший и правильный, но мне потребовалось некоторое время, чтобы понять, что я также могу использовать его для создания полностью пустого массива.

l =  [[] for _ in range(3)]

результаты

[[], [], []]

вы должны составить список списков, и лучший способ-использовать вложенные понимания:

>>> matrix = [[0 for i in range(5)] for j in range(5)]
>>> pprint.pprint(matrix)
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]

на [5][5] пример, вы создаете список с целым числом " 5 " внутри и пытаетесь получить доступ к его 5-му элементу, и это, естественно, вызывает IndexError, потому что нет 5-го элемента:

>>> l = [5]
>>> l[5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

объявить матрицу нулей (единиц):

numpy.zeros((x, y))

например

>>> numpy.zeros((3, 5))
    array([[ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.]])

или и NumPy.одни ((x, y)) например,

>>> np.ones((3, 5))
array([[ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.]])

даже трех размеров. (http://www.astro.ufl.edu / ~warner/prog/python.html см. -- > многомерные массивы)


переписать для удобства чтения:

# 2D array/ matrix

# 5 rows, 5 cols
rows_count = 5
cols_count = 5

# create
#     creation looks reverse
#     create an array of "cols_count" cols, for each of the "rows_count" rows
#        all elements are initialized to 0
two_d_array = [[0 for j in range(cols_count)] for i in range(rows_count)]

# index is from 0 to 4
#     for both rows & cols
#     since 5 rows, 5 cols

# use
two_d_array[0][0] = 1
print two_d_array[0][0]  # prints 1   # 1st row, 1st col (top-left element of matrix)

two_d_array[1][0] = 2
print two_d_array[1][0]  # prints 2   # 2nd row, 1st col

two_d_array[1][4] = 3
print two_d_array[1][4]  # prints 3   # 2nd row, last col

two_d_array[4][4] = 4
print two_d_array[4][4]  # prints 4   # last row, last col (right, bottom element of matrix)

Я на своем первом скрипте Python, и я был немного смущен примером квадратной матрицы, поэтому я надеюсь, что приведенный ниже пример поможет вам сэкономить время:

 # Creates a 2 x 5 matrix
 Matrix = [[0 for y in xrange(5)] for x in xrange(2)]

, Так что

Matrix[1][4] = 2 # Valid
Matrix[4][1] = 3 # IndexError: list index out of range

использование:

matrix = [[0]*5 for i in range(5)]

*5 для первого измерения работает, потому что на этом уровне данные неизменяемы.


используя NumPy, вы можете инициализировать пустую матрицу следующим образом:

import numpy as np
mm = np.matrix([])

и позже добавить данные, как это:

mm = np.append(mm, [[1,2]], axis=1)

Я читаю в файлах, разделенных запятыми, как это:

data=[]
for l in infile:
    l = split(',')
    data.append(l)

список "данные" - это список списков с индексными данными[строка][col]


# Creates a list containing 5 lists initialized to 0
Matrix = [[0]*5]*5

будьте осторожны с этим коротким выражением, см. полное объяснение в ответе @F. J


использование:

import copy

def ndlist(*args, init=0):
    dp = init
    for x in reversed(args):
        dp = [copy.deepcopy(dp) for _ in range(x)]
    return dp

l = ndlist(1,2,3,4) # 4 dimensional list initialized with 0's
l[0][1][2][3] = 1

Я думаю, что NumPy-это путь. Вышеуказанное является общим, если вы не хотите использовать NumPy.


что это словарь сделано для!

matrix = {}

вы можете определить ключи и значения двумя способами:

matrix[0,0] = value

или

matrix = { (0,0)  : value }

результат:

   [ value,  value,  value,  value,  value],
   [ value,  value,  value,  value,  value],
   ...

Если вы хотите иметь возможность думать об этом как о 2D-массиве, а не думать в терминах списка списков (что, на мой взгляд, более естественно), вы можете сделать следующее:

import numpy
Nx=3; Ny=4
my2Dlist= numpy.zeros((Nx,Ny)).tolist()

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


rows = int(input())
cols = int(input())

matrix = []
for i in range(rows):
  row = []
  for j in range(cols):
    row.append(0)
  matrix.append(row)

print(matrix)

почему такой длинный код, что тоже в Python вы спрашиваете?

давно, когда мне было неудобно с Python, я увидел однострочные ответы для написания 2D-матрицы и сказал себе, что больше не буду использовать 2-D матрицу в Python. (Эти отдельные строки были довольно страшными, и это не дало мне никакой информации о том, что делал Python. Также обратите внимание, что я не знаю этих сокращений.)

в любом случае, вот код для новичка, чей выход из C, CPP и Java в фоне

Примечание Для любителей и экспертов Python: пожалуйста, не голосуйте только потому, что я написал подробный код.


Если у вас нет информации о размере перед запуском, создайте два одномерных списка.

список 1: для хранения строк список 2: фактическая двумерная матрица

сохраните всю строку в 1-м списке. После этого добавьте список 1 в список 2:

from random import randint


coordinates=[]
temp=[]
points=int(raw_input("Enter No Of Coordinates >"))
for i in range(0,points):
    randomx=randint(0,1000)
    randomy=randint(0,1000)
    temp=[]
    temp.append(randomx)
    temp.append(randomy)
    coordinates.append(temp)

print coordinates

выход:

Enter No Of Coordinates >4
[[522, 96], [378, 276], [349, 741], [238, 439]]

С помощью списка :

matrix_in_python  = [['Roy',80,75,85,90,95],['John',75,80,75,85,100],['Dave',80,80,80,90,95]]

С помощью dict: вы также можете сохранить эту информацию в хэш-таблице для быстрого поиска, как

matrix = { '1':[0,0] , '2':[0,1],'3':[0,2],'4' : [1,0],'5':[1,1],'6':[1,2],'7':[2,0],'8':[2,1],'9':[2,2]};

матрица ['1'] даст вам результат в O (1) time

* nb: вам нужно иметь дело с столкновением в хэш-таблице


Так я обычно создаю 2D-массивы в python.

col = 3
row = 4
array = [[0] * col for _ in range(row)]

Я считаю, что этот синтаксис легко запомнить по сравнению с использованием для циклов в понимании списка.