Двумерный массив — это структура данных, которая хранит информацию в виде таблицы строк и столбцов. Это как шахматная доска бесконечных размеров: у каждой ячейки есть номер, а внутри она хранит какое-то значение, например ячейка пуста или занята фигурой.
В программировании такие массивы используют для разных целей: работы с таблицами, изображениями (потому что пиксели тоже двумерный массив) или игровыми полями (как в «Крестиках-ноликах»).
Сегодня рассказываем, как создать такой массив в языке программирования Python и управлять им.
Введение в двумерные массивы
Чтобы понять массивы, нужно сначала вспомнить, что такое списки.
Списки в Python — упорядоченная изменяемая коллекция элементов любого типа, допустимо даже смешивать типы между собой. Списки можно изменять по ходу выполнения программы, их не нужно пересоздавать и выделять память отдельно.
Списки выделяются квадратными скобками, элементы разделяются запятой:
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
В качестве элементов списка могут быть другие списки.
Двумерный массив Python реализуется как раз как список списков. Пример такого массива — таблица температур за неделю:
# строки — дни недели; столбцы — утро, день, вечер
temperature = [
# понедельник:
[12, 18, 15],
# вторник:
[10, 16, 14],
# среда:
[11, 17, 13]
]
Получается, что значения лежат как бы на пересечении строки и столбца. Например, 18 градусов находится на пересечении столбца «День» и строки «Понедельник», а 13 градусов — на пересечении «Вечер» и «Среда».
Способы создания двумерных массивов
В Python есть несколько способов создать двумерный массив. Самый простой — вручную перечислить все элементы. Но если массив большой, удобнее заполнить его автоматически с помощью циклов или генераторов списков.
Для начала можно создать шаблон-болванку: таблицу умножения или пустое поле для игры, где все клетки заполнены нулями. После этого каждый элемент можно заменить на тот, что действительно нужен в реальной программе. При этом нужно не забыть, что каждая строка — отдельный список внутри основного списка.
Создание массива с использованием цикла:
# создание массива 3×3, заполненного нулями
matrix = []
for i in range(3):
# создаём строку из трёх нулей
row = [0] * 3
# добавляем строку в матрицу
matrix.append(row)
# выводим массив построчно с отступами
for row in matrix:
print(' '.join(map(str, row)))
Другой вариант создания массива — через генератор списков:
# [0] * 3 создаёт список из 3 нулей
# _ - элемент итерируемого объекта или диапазона
# range(3) - диапазон из 3 повторений
matrix = [[0] * 3 for _ in range(3)]
# выводим массив построчно с отступами
for row in matrix:
print(' '.join(map(str, row)))
Оба варианта выведут одно и то же. Мы добавили аккуратное форматирование при выводе, поэтому будет так:
0 0 0
0 0 0
0 0 0
Самая частая ошибка при создании массивов
Может показаться, что есть ещё один простой способ создания массива: создать массив из элементов, количество которых будет равно количеству столбцов. А потом умножить этот массив на количество строк.
С нулями это будет выглядеть так:
wrong_array = [[0] * 3] * 3
В чём тут проблема: мы создаём один список из 3 нулей, а потом 3 раза дублируем на него ссылку. В итоге получается, что все строки в памяти будут представлять собой один и тот же список, поэтому, если изменить элемент в одной строке, он изменится во всех остальных.
Сейчас наш массив выводит то же самое, что и предыдущие:
0 0 0
0 0 0
0 0 0
Теперь попробуем заменить первый ноль на другое число:
# меняем первый ноль в первой строке
wrong_array[0][0] = 7
# выводим массив построчно с отступами
for row in wrong_array:
print(' '.join(map(str, row)))
Мы изменили только один список, но в результате изменились все:
7 0 0
7 0 0
7 0 0
Генераторы списков и циклы создают отдельные списки для каждой строки, поэтому такой способ правильный и безопасный.
Инициализация двумерного массива
Инициализация — это процесс задания начальных значений массива. Можно заполнить его:
- Одинаковыми значениями. В наших примерах мы заполнили массивы нулями.
- Последовательными числами. Например, для тестовых данных.
- Случайными числами. Может понадобиться для генерации карты в игре.
Заполнить массив конкретными значениями можно как вручную, так и автоматически. Вот пример ручной инициализации и через генератор списков:
# инициализация вручную
matrix = [
[1, 2],
[3, 4]
]
for row in matrix:
print(' '.join(map(str, row)))
# добавляем пустую строку между выводами
print()
# инициализация через генератор списка.
# каждый элемент считается по формуле так,
# чтобы все числа шли по порядку
matrix = [[i * 3 + j for j in range(3)] for i in range(3)]
# выводим массив построчно с отступами
for row in matrix:
print(' '.join(map(str, row)))
При запуске получаем два варианта массива:
1 2
3 4
0 1 2
3 4 5
6 7 8
Способы ввода двумерных массивов
Данные в массиве можно задавать несколькими способами:
- Вручную, то есть прописать значения прямо в коде. Это подходит только для небольших массивов.
- С клавиатуры — попросить пользователя ввести числа.
- Из файла — считать готовую таблицу из CSV или текстового файла.
Для примера напишем небольшую программу, в которой пользователь будет сам вводить элементы массива с клавиатуры. Ещё добавим обработку ошибок и подробные указания, что и когда вводить.
Сначала запрашиваем количество строк и столбцов:
# запрашиваем у пользователя количество строк
print("Введите количество строк матрицы (n):")
# преобразуем введённую строку в целое число
n = int(input())
# запрашиваем у пользователя количество столбцов
print("Введите количество столбцов матрицы (m):")
# преобразуем введённую строку в целое число
m = int(input())
Создаём пустую матрицу, двумерный массив:
# инициализируем пустую матрицу
matrix = []
Реализуем построчный ввод. Для этого попросим пользователя вводить элементы матрицы через пробел:
print(f"\nВведите {n} строк матрицы, в каждой строке {m} чисел, разделённых пробелами:")
После каждой строки нужно нажимать Enter.
Для такого ввода нам понадобится цикл. На каждой итерации принимаем от пользователя строку, разбиваем её по пробелам, преобразуем в числа и создаём из этих чисел список. Этот список будет являться строкой будущего массива.
# считываем матрицу построчно
for i in range(n):
# цикл для повторного ввода при ошибке
while True:
try:
print(f"Строка {i + 1}: ", end="")
# читаем строку, разбиваем по пробелам, преобразуем в числа
row = list(map(int, input().split()))
После этого проверяем, что пользователь ввёл нужное количество чисел — то есть количество столбцов, которые он указал в начале:
# проверяем, что введено правильное количество чисел
if len(row) != m:
print(f"Ошибка! Должно быть {m} чисел. Попробуйте ещё раз.")
continue
Если количество чисел неправильное, выдаём ошибку и запускаем цикл снова. Если всё верно, добавляем список в массив:
# добавляем строку в матрицу
matrix.append(row)
# выходим из цикла при успешном вводе
break
except ValueError:
print("Ошибка! Вводите только числа, разделённые пробелами. Попробуйте ещё раз.")
Выводим форматированный результат на экран:
# выводим результат
print("\nПолученная матрица:")
for i in range(n):
for j in range(m):
# форматированный вывод с отступами
print(f"{matrix[i][j]:5}", end=" ")
# переход на новую строку после вывода строки матрицы
print()
Смотрим, как это работает:
Способы вывода двумерных массивов
Как можно вывести двумерный массив на экран:
- Целиком — напечатать все строки подряд. Тогда матрица будет отображена в одну строку, то есть все одномерные списки будут идти через запятую.
- Поэлементно — обойти вложенными циклами. В этом варианте двумерный массив будет выглядеть как таблица. Списки могут быть в квадратных скобках, а могут без — это зависит от кода.
- Выборочно — только определённые строки или столбцы.
Самый простой вывод всей матрицы поэлементно выглядит так:
# создаём двумерный массив через генератор списков
dimensional = [[i * 3 + j for j in range(3)] for i in range(3)]
# выводим заголовок для вывода
print("\nМатрица:\n")
for row in dimensional:
# каждая строка выводится в отдельной строке
print(row)
Что на экране при запуске:
Матрица:
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
Вывод определённых столбца и строки массива
Ещё раз вспомним, чем являются строки и столбцы двумерных массивов:
- Столбец — это все элементы с одинаковым индексом в разных строках.
- Строка — это один из вложенных списков.
Возьмём для примера наш массив с температурами:
# строки — дни недели; столбцы — утро, день, вечер
temperature = [
# понедельник:
[12, 18, 15],
# вторник:
[10, 16, 14],
# среда:
[11, 17, 13]
]
Столбец 1 — это все дневные температуры, потому что отсчёт начинается с 0:
# вывод второго столбца (индекс 1)
print("Второй столбец:")
for row in temperature:
print(row[1])
Вывод:
Второй столбец:
18
16
17
Первая строка — это данные за понедельник:
# вывод первой строки (индекс 0)
print("Первая строка:")
print(temperature[0])
Запускаем код:
Первая строка:
[12, 18, 15]
Обработка элементов двумерного массива
Двумерные массивы можно не только создавать и выводить, но и сортировать, изменять, удалять элементы. Это можно использовать для анализа данных в таблицах или обновления игрового поля.
Все двумерные массивы просто наборы списков, поэтому и их обработка совпадает с теми же операциями над списками. Питон предоставляет удобные встроенные механизмы для этой работы даже без таких сложных дополнительных библиотек, как NumPy.
Вот несколько примеров. Работать будем с таким массивом:
matrix = [
[5, 2, 8],
[1, 4, 3],
[9, 6, 7]
]
Сортировка строк двумерного массива
Это позволяет упорядочить данные в массиве. Например, отсортировать оценки студентов по возрастанию или таблицу товаров по цене.
Сортируем первую строку:
# сортируем первую строку (индекс 0) по возрастанию
matrix[0].sort()
# выводим на экран
print("Массив с отсортированной первой строкой:")
for row in matrix:
print(' '.join(map(str, row)))
После сортировки:
Массив с отсортированной первой строкой:
Массив с отсортированной первой строкой:
2 5 8
1 4 3
9 6 7
Обновление значений в двумерном массиве
Иногда нужно изменить конкретный элемент или целую строку. Например, обновить цену товара в таблице или состояние пикселя в изображении.
Меняем элемент в одной строке:
# меняем значение во второй строке, третьем столбце (индексы 1, 2)
matrix[1][2] = 99
# выводим на экран
print("Массив с изменённым значением во второй строке и третьем столбце:")
for row in matrix:
print(' '.join(map(str, row)))
Обновлённый массив:
Массив с изменённым значением во второй строке и третьем столбце:
2 5 8
1 4 99
9 6 7
Удаление значений из двумерного массива
Можно удалять отдельные элементы или целые строки. Например, если товар закончился, его можно убрать из таблицы.
Удаляем элемент:
# удаляем второй элемент из первой строки (индекс 1)
del matrix[0][1]
# выводим на экран
print("Массив с удалённым значением в первой строке:")
for row in matrix:
print(' '.join(map(str, row)))
Запускаем код:
Массив с удалённым значением в первой строке:
2 8
1 4 99
9 6 7
Примеры обработки двумерного массива
Вот ещё два примера, что можно делать с массивами.
Находим максимальный элемент:
# поиск максимального элемента
max_value = max(max(row) for row in matrix)
print("Максимальное значение:", max_value)
Проверяем, что нашла функция:
Максимальное значение: 99
Считаем сумму всех элементов:
# сумма всех элементов
total = sum(sum(row) for row in matrix)
print("Сумма всех элементов:", total)
Считаем сумму:
Сумма всех элементов: 136
Навигация по двумерным массивам
Для работы с двумерными массивами нужно получать доступ к его элементам и перебирать их. Каждый элемент имеет два индекса:
- Первый — номер строки.
- Второй — номер столбца.
Отсчёт обоих индексов начинается с 0. То есть первый элемент первой строки будет иметь индексы [0][0]
.
Для практики создадим такой массив:
# создаём массив
matrix = [
["A", "B", "C"],
["D", "E", "F"],
["G", "H", "I"]
]
Получаем доступ к конкретному элементу:
# получаем элемент во второй строке, третьем столбце (индексы 1, 2)
element = matrix[1][2]
print(element)
Проверяем, что выводится в консоли:
F
А вот как различаются способы вывода массива. Выведем массив дважды — как список списков и просто как значения элементов:
# выводим массив с обозначением элементов
for row in matrix:
print(row)
# выводим массив поэлементно — только значения
for row in matrix:
for element in row:
# при выводе разделяем значения пробелами
print(element, end=" ")
Теперь сразу понятно, как различается внешний вид вывода:
['A', 'B', 'C']
['D', 'E', 'F']
['G', 'H', 'I']
A B C
D E F
G H I
Вам слово
Приходите к нам в соцсети поделиться своим мнением о двумерных массивах в Python и почитать, что пишут другие. А ещё там выходит дополнительный контент, которого нет на сайте — шпаргалки, опросы и разная дурка. В общем, вот тележка, вот ВК — велком!