9

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

3

Проблема: Ошибка при инициализации двумерного массива в Python

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

Matrix = [][]

Однако при попытке этого кода я получаю следующую ошибку:

IndexError: list index out of range

Проблема заключается в том, что я не могу создать пустой массив списков таким образом. Есть ли правильный способ инициализировать двумерный массив в Python без использования библиотеки NumPy? Любая помощь будет очень полезна!

5 ответ(ов)

12

Вы, по сути, пытаетесь индексировать неинициализированный массив. Сначала нужно инициализировать внешний список, создав внутри него списки, прежде чем добавлять элементы. В Python это называется "генерация списка" (list comprehension).

# Создает список, содержащий 5 списков, каждый из которых состоит из 8 элементов, инициализированных нулями
w, h = 8, 5
Matrix = [[0 for x in range(w)] for y in range(h)] 

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

Matrix[0][0] = 1
Matrix[6][0] = 3 # ошибка! выход за пределы диапазона 
Matrix[0][6] = 3 # корректно

Обратите внимание, что матрица имеет "порядок по y", другими словами, "индекс y" идет перед "индексом x".

print(Matrix[0][0]) # выводит 1
x, y = 0, 6 
print(Matrix[x][y]) # выводит 3; будьте внимательны с индексированием!

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

4

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

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

Как видно из примера, изменение одного элемента в последнем списке влияет на все остальные. Чтобы избежать этой проблемы, используйте первый способ с использованием генератора списков.

1

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

matrix = [[]]

А если вы хотите сгенерировать матрицу размером 5, заполненную нулями, используйте следующий код:

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

Обратите внимание, что в Python 3 вместо xrange следует использовать range.

0

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

Matrix = {}

После этого вы можете делать так:

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

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

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

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

0

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

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

В этом случае matrix[0][0] будет равно 2, а matrix[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)]

Этот код создает список, который содержит 10 списков, каждый из которых включает числа, соответствующие определенному диапазону.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь