Как определить двумерный массив?
Проблема: Ошибка при инициализации двумерного массива в 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 списков, каждый из которых включает числа, соответствующие определенному диапазону.
Как получить последний элемент списка?
Как клонировать список, чтобы он не изменялся неожиданно после присваивания?
Самый быстрый способ проверить наличие значения в списке
Преобразование всех строк в списке в целые числа
Нахождение среднего значения списка