- Lesson 9 Двумерные списки (массивы)
- 1. Вложенные списки: обработка и печать
- 2. Вложенные списки: создание
- 3. Как вы вводите двумерный массив?
- 4. Обработка двумерного массива: пример
- 5. Двумерные массивы: вложенные генераторы
- Двумерные массивы в Python и методы работы с ними
- Создание двумерных массивов
- Способы ввода двумерных массивов
- Вывод двумерных массивов
- Обработка двумерных массивов
- Итог
Lesson 9
Двумерные списки (массивы)
1. Вложенные списки: обработка и печать
В реальном мире часто задачам приходится хранить прямоугольную таблицу данных. [скажем больше об этом!] Такие таблицы называются матрицами или двумерными массивами. В Python любая таблица может быть представлена как список списков (список, где каждый элемент, в свою очередь, является списком). Например, вот программа, которая создает числовую таблицу с двумя строками и тремя столбцами, а затем выполняет некоторые манипуляции с ней:
a = [[1, 2, 3], [4, 5, 6]] print(a[0]) print(a[1]) b = a[0] print(b) print(a[0][2]) a[0][1] = 7 print(a) print(b) b[2] = 9 print(a[0]) print(b)
Первый элемент a здесь — a[0] — это список чисел [1, 2, 3] . Первый элемент этого нового списка — a[0][0] == 1 ; кроме того, a[0][1] == 2 , a[0][2] == 3 , a[1][0] == 4 , a[1][1] == 5 , a[1][2] == 6 .
Для обработки двумерного массива обычно используются вложенные циклы. Первый цикл повторяется через номер строки, второй цикл проходит через элементы внутри строки. Например, так вы показываете двумерный численный список на экране по строкам, разделяя числа пробелами:
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] for i in range(len(a)): for j in range(len(a[i])): print(a[i][j], end=' ') print()
Мы уже пытались объяснить, что переменная for-loop в Python может выполнять итерацию не только по range() , но обычно по всем элементам любой последовательности. Последовательности в Python — это списки и строки (и некоторые другие объекты, которые мы еще не встретили). Посмотрите, как вы можете печатать двумерный массив, используя эту удобную функцию цикла for :
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] for row in a: for elem in row: print(elem, end=' ') print()
Естественно, для вывода одной строки вы можете использовать метод join() :
for row in a: print(' '.join([str(elem) for elem in row]))
Так вы можете использовать 2 вложенных цикла для вычисления суммы всех чисел в двумерном списке:
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] s = 0 for i in range(len(a)): for j in range(len(a[i])): s += a[i][j] print(s)
Или то же самое с итерацией элементами, а не переменными i и j :
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] s = 0 for row in a: for elem in row: s += elem print(s)
2. Вложенные списки: создание
Предположим, что указаны два числа: число строк n и количество столбцов m . Вы должны создать список размером n × m , заполненный, скажем, нулями.
Очевидное решение кажется неправильным:
Это можно легко увидеть, если вы установите значение a[0][0] на 5 , а затем распечатаете значение a[1][0] — оно также будет равно 5. Причина в том, что [0] * m возвращает только ссылку на список из m нулей, но не список. Последующее повторение этого элемента создает список из n элементов, все ссылки на один и тот же список (как и операция b = a для списков не создает новый список), поэтому все строки в результирующем списке на самом деле одинаковы строка.
Используя наш визуализатор, отслеживайте идентификатор списков. Если два списка имеют одинаковый номер id, это фактически тот же список в памяти.
n = 3 m = 4 a = [[0] * m] * n a[0][0] = 5 print(a[1][0])
Таким образом, двумерный список не может быть создан просто путем повторения строки. Что делать.
Возможный способ: вы можете создать список из n элементов (например, из n нулей), а затем сделать каждый из элементов ссылкой на другой одномерный список из m элементов:
n = 3 m = 4 a = [0] * n for i in range(n): a[i] = [0] * m
Другой (но похожий) способ: создать пустой список, а затем append к нему новый элемент n раз (этот элемент должен быть списком длины m ):
n = 3 m = 4 a = [] for i in range(n): a.append([0] * m)
Но самый простой способ — использовать генератор, создавая список из n элементов, каждый из которых представляет собой список из m нулей:
n = 3 m = 4 a = [[0] * m for i in range(n)]
В этом случае каждый элемент создается независимо от других. Список [0] * m n раз помечается как новый, и копирование ссылок не происходит.
3. Как вы вводите двумерный массив?
Скажем, программа принимает входной двумерный массив в виде n строк, каждый из которых содержит m чисел, разделенных пробелами. Как заставить программу читать ее? Пример того, как вы можете это сделать:
# первая строка ввода - это количество строк массива n = int(input()) a = [] for i in range(n): a.append([int(j) for j in input().split()])
Или, не используя сложные вложенные вызовы:
# первая строка ввода - это количество строк массива n = int(input()) a = [] for i in range(n): row = input().split() for i in range(len(row)): row[i] = int(row[i]) a.append(row)
Вы можете сделать то же самое с генераторами:
# первая строка ввода - это количество строк массива n = int(input()) a = [[int(j) for j in input().split()] for i in range(n)]
4. Обработка двумерного массива: пример
Предположим, вам задан квадратный массив (массив из n строк и n столбцов). Предположим, вы должны установить элементы главной диагонали, равные 1 (т. Е. Те элементы a[i][j] для которых i==j ), чтобы установить элементы выше, чем диагональ, равная 0, и установить элементы ниже этой диагонали, равной 2. То есть вам нужно создать такой массив (пример для n==4 ):
1 0 0 0 2 1 0 0 2 2 1 0 2 2 2 1
(В этом случае вы можете сделать это вручную, установив a[0][0] = 1 , a[0][1] = 0 и т. Д., Но вы не будете делать это вручную для массивов из 100 строк и 100 столбцов , что часто бывает.)
Мы стремимся показать вам несколько способов решения этой проблемы. Во-первых, обратите внимание, что элементы, лежащие над главной диагональю, — это элементы a[i][j] для которых ij . Таким образом, мы можем сравнить значения i и j , определяющие значение a[i][j] . Мы получаем следующий алгоритм:
n = 4 a = [[0] * n for i in range(n)] for i in range(n): for j in range(n): if i < j: a[i][j] = 0 elif i >j: a[i][j] = 2 else: a[i][j] = 1 for row in a: print(' '.join([str(elem) for elem in row]))
Этот алгоритм медленный: он использует два цикла и для каждой пары (i,j) выполняет одну или две команды if . Если мы усложним алгоритм, мы сможем сделать это без условного оператора.
Сначала заполните основную диагональ, для которой нам понадобится один цикл:
Затем заполните нулями все элементы над главной диагональю. Чтобы сделать это, для каждой строки с номером i вам нужно присвоить значение a[i][j] для j = i+1 , . n-1 . Для этого вам нужны вложенные циклы:
for i in range(n): for j in range(i + 1, n): a[i][j] = 0
По аналогии, для j = 0 , . i-1 задайте элементы a[i][j] равными 2 :
for i in range(n): for j in range(0, i): a[i][j] = 2
Вы можете комбинировать весь этот код и получить другое решение:
n = 4 a = [[0] * n for i in range(n)] for i in range(n): for j in range(0, i): a[i][j] = 2 a[i][i] = 1 for j in range(i + 1, n): a[i][j] = 0 for row in a: print(' '.join([str(elem) for elem in row]))
Вот еще одно решение, которое повторяет списки для создания следующих строк списка. i строка списка состоит из i чисел 2 , за которым следует одно целое число 1 , за которым следуют ni-1 нули:
n = 4 a = [0] * n for i in range(n): a[i] = [2] * i + [1] + [0] * (n - i - 1) for row in a: print(' '.join([str(elem) for elem in row]))
Как обычно, вы можете заменить петлю генератором:
n = 4 a = [0] * n a = [[2] * i + [1] + [0] * (n - i - 1) for i in range(n)] for row in a: print(' '.join([str(elem) for elem in row]))
5. Двумерные массивы: вложенные генераторы
Вы можете использовать вложенные генераторы для создания двумерных массивов, поместив генератор списка, который является строкой, внутри генератора всех строк. Напомним, что вы можете создать список из n строк и m столбцов с помощью генератора (который создает список из n элементов, где каждый элемент представляет собой список из m нулей):
Но внутренний список также может быть создан с использованием, например, такого генератора: [0 for j in range(m)] . Вложив один генератор в другой, получим
[[0 for j in range(m)] for i in range(n)]
Как это связано с нашей проблемой? Дело в том, что если число 0 заменяется некоторым выражением, которое зависит от i (номер строки) и j (номер столбца), вы получаете заполненную матрицу согласно некоторой формуле.
Например, предположим, что вам нужно инициализировать следующий массив (для удобства добавляются дополнительные пробелы между элементами):
0 0 0 0 0 0 0 1 2 3 4 5 0 2 4 6 8 10 0 3 6 9 12 15 0 4 8 12 16 20
В этом массиве есть n = 5 строк, m = 6 столбцов, а элемент с индексом строки i и индексом столбца j вычисляется по формуле a[i][j] = i * j .
Как всегда, вы можете использовать генератор для создания такого массива:
[[i * j for j in range(m)] for i in range(n)]
Двумерные массивы в Python и методы работы с ними
Иногда нам приходится использовать таблицы с данными для решения своих задач. Такие таблицы называются матрицами или двумерными массивами.
В Python подобные таблицы можно представить в виде списка, элементы которого являются другими списками. Для примера создадим таблицу с тремя столбцами и тремя строками, заполненными произвольными буквами:
mas = [['й', 'ц', 'у'], ['к','е','н'], ['г', 'ш', 'щ']] #Вывод всего двумерного массива print(mas) #Вывод первого элемента в первой строке print(mas[0][0]) # Выведет й #Вывод третьего элемента в третьей строке print(mas[2][2]) # Выведет щ
Создание двумерных массивов
Создать такой массив в Python можно разными способами. Разберем первый:
# Создание таблицы с размером 3x3, заполненной нулями a = 3 mas = [0] * a for i in range(a): mas[i] = [0] * a print(mas) # Выведет [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Второй способ предполагает создание пустого списка с добавлением в него новых списков. Рассмотрим на примере:
# Создание таблицы с размером 2x2, заполненной единицами
a = 2 mas = [] for i in range(a): mas.append([0] * a) print(mas) # Выведет [[1, 1, 1], [1, 1, 1], [1, 1, 1]]
Третьим и самым простым способом является генератор списков с x строками, которые будут состоять из y элементов. Пример:
# Создание таблицы с размером 3x3, заполненной двойками a = 3 mas = [[2] * a for i in range(a)] print(mas) # Выведет [[2, 2, 2], [2, 2, 2], [2, 2, 2]]
Способы ввода двумерных массивов
Допустим, нам нужно ввести двумерный массив после запуска нашей программы. Для этого мы можем создать программу, которая будет построчно считывать значения нашего массива, а также количество строк в нем. Рассмотрим на примере:
a=int(input()) mas = [] for i in range(a): mas.append(list(map(int, input().split()))) print(mas)
Запускаем программу и сначала вводим количество строк в массиве (допустим, 3). Далее вводим строки в порядке их очереди. Например:
После этого данная программа выведет наш двумерный массив: [[1, 1, 1], [1, 1, 1], [1, 1, 1]].
То же самое можно сделать с помощью генератора двумерных массивов:
mas = [list(map(int, input().split())) for i in range(int(input()))] # Вводим 3 1 1 1 1 1 1 1 1 1 print(mas) # Выведет [[1, 1, 1], [1, 1, 1], [1, 1, 1]]
Вывод двумерных массивов
Для обработки и вывода списков используются два вложенных цикла. Первый цикл – по порядковому номеру строки, второй – по ее элементам. Например, вывести массив можно так:
mas = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] for i in range(0, len(mas)): for i2 in range(0, len(mas[i])): print(mas[i][i2], end=' ') print() # Выведет 1 1 1 1 1 1 1 1 1
То же самое можно сделать не по индексам, а по значениям массива:
mas = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] for i in mas: for i2 in i: print(i2, end=' ') print() # Выведет 1 1 1 1 1 1 1 1 1
Способ с использованием метода join():
mas = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] for i in mas: print(' '.join(list(map(str, i)))) # Выведет 1 1 1 1 1 1 1 1 1
Вывод одной из строк двумерного массива можно осуществить с помощью цикла и того же метода join(). Для примера выведем вторую строку в произвольном двумерном массиве:
mas = [[1, 1, 1], [2, 2, 2], [3, 3, 3]] string = 2 for i in mas[string-1]: print(i, end=' ') # Выведет 1 1 1
Для вывода определенного столбца в двумерном массиве можно использовать такую программу:
mas = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] column = 2 for i in mas: print(i[column-1], end=' ') # Выведет 2 5 8
Обработка двумерных массивов
Составим произвольный двумерный массив с числами и размерностью 4×4:
2 4 7 3 4 5 6 9 1 0 4 2 7 8 4 7
Теперь поставим числа в каждой строке по порядку:
mas = [[2, 4, 7, 3], [4, 5, 6, 9], [1, 0, 4, 2], [7, 8, 4, 7]] mas2 = [] for i in mas: mas2.append(sorted(i)) print(mas2) # Выведет [[2, 3, 4, 7], [4, 5, 6, 9], [0, 1, 2, 4], [4, 7, 7, 8]]
А теперь расставим все числа по порядку, вне зависимости от их нахождения в определенной строке:
mas = [[2, 4, 7, 3], [4, 5, 6, 9], [1, 0, 4, 2], [7, 8, 4, 7]] mas2 = [] for i in mas: for i2 in i: mas2.append(i2) mas=sorted(mas2) for x in range(0, len(mas), 4): e_c = mas[x : 4 + x] if len(e_c) < 4: e_c = e_c + [None for y in range(n - len(e_c))] print(list(e_c)) # Выведет [0, 1, 2, 2] [3, 4, 4, 4] [4, 5, 6, 7] [7, 7, 8, 9]
Итог
Мы разобрались в основах двумерных массивов в Python, научились создавать, вводить и выводить их, а также рассмотрели примеры обработки. Надеюсь, статья оказалась полезной для вас!