Как определить двумерный массив?
Проблема: Ошибка при инициализации двумерного массива в Python
Я хочу определить двумерный массив без предварительной инициализации длины, используя следующий код:
Matrix = [][]
Однако при попытке этого кода я получаю следующую ошибку:
IndexError: list index out of range
Проблема заключается в том, что я не могу создать пустой массив списков таким образом. Есть ли правильный способ инициализировать двумерный массив в Python без использования библиотеки NumPy? Любая помощь будет очень полезна!
5 ответ(ов)
Вы, по сути, пытаетесь индексировать неинициализированный массив. Сначала нужно инициализировать внешний список, создав внутри него списки, прежде чем добавлять элементы. В 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" для внутренних и внешних списков и хотите создать прямоугольную матрицу.
Вот более короткий способ инициализации списка списков:
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, заполненную нулями, используйте следующий код:
matrix = [[0 for i in range(5)] for j in range(5)]
Обратите внимание, что в Python 3 вместо xrange
следует использовать range
.
Если вам нужен двухмерный контейнер для хранения некоторых элементов, вы можете удобно использовать словарь:
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)
В этом случае 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 списков, каждый из которых включает числа, соответствующие определенному диапазону.
Почему используется string.join(list), а не list.join(string)?
Как клонировать список, чтобы он не изменялся неожиданно после присваивания?
Как вернуть ключи словаря в виде списка в Python?
Как отсортировать список/кортеж списков/кортежей по элементу на заданном индексе
Как преобразовать строковое представление списка в список?