Занятие № 7. Применение списков для решения задач

Цель: научиться применять одномерные списки для решения задач.

Теория

Создание списка

Список - это набор упорядоченных и пронумерованных элементов. Каждый элемент списка - это значение любого встроенного или определённого программистом типа. В Python списки имеют тип list.

Самый простой способ создать список - заключить его элементы в квадратные скобки и разделить запятой:

fib = [1, 1, 2, 3, 5, 8, 13]
goods = ["хлеб", "молоко", "мука"]

В Python элементы списка не обязательно должны быть одного типа:

arr = [12, True, [456]]

Чтобы объявить пустой список, квадратные скобки оставляют пустыми:

lst = [] # пустой список
Смешивание типов

Хорошей практикой считается не смешивать в списке значения разных типов, несмотря на то, что это не запрещено синтаксисом языка. Проще отладить код со списками, в которых хранятся значения одного типа.

Оператор индексирования списка

Элементы списка пронумерованы и к ним можно обращаться по их индексу. Нумерация элементов списка начинается с нуля.

Рисунок 1: Индексирование списка

Получить элемент списка по его индексу можно с помощью оператора [ ].

fib = [1, 1, 2, 3, 5, 8, 13]
print(fib[2])
print(fib[9-8])
print(fib[-2])

      
fib = [1, 1, 2, 3, 5, 8, 13]
print(fib[2])
print(fib[9-8])
print(fib[-2])

Когда индекс отрицателен, это значит, что мы отсчитываем номер элемента x справа налево.

Что выведется на экран после выполнения следующей программы:

alist = [3, 67, "кот", [56, 57, "Python"], [ ], 3.14, False]
print(alist[5])

Верно. Отсчёт элементов начинается с 0. Список [56, 57, "Python"] и [ ] также считаются за один элемент.

Индекс пустого списка равен 4.

Отсчёт индексов начинается с 0. Индекс элемента False - 6.

Строка "Python" находится в списке, который сам по себе будет элементом списка alist. Весь этот вложенный список считается за один элемент списка alist.

Списки относятся к изменяемому типу данных. Мы можем заменить значение, которое находится по заданному индексу:

myList = [0, 1, 4, 6]
print(myList[2])
myList[2] = 0 # меняем элемент с индексом 2 на 0
print(myList)

      
myList = [0, 1, 4, 6]
print(myList[2])
myList[2] = 0 # меняем элемент с индексом 2 на 0
print(myList)

Элементами списка могут быть другие списки. Чтобы получить элемент из вложенного списка операторы индексирования записываются последовательно:

magic_sq = [
    [2, 7, 6],
    [9, 5, 1],
    [4, 3, 8]
]

print(magic_sq[1][2]) # вторая строка, третий столбец

      
magic_sq = [
    [2, 7, 6],
    [9, 5, 1],
    [4, 3, 8]
]

print(magic_sq[1][2]) # вторая строка, третий столбец

В списке magic_sq хранится x ? элемента. Чтобы получить из этого списка элемент первой строки и второго столбца нужно записать x magic_sq[0][1].

Количество элементов списка

С помощью функции len() можно узнать количество элементов в списке:

fib = [1, 1, 2, 3, 5, 8, 13]
print(len(fib))

      
fib = [1, 1, 2, 3, 5, 8, 13]
print(len(fib))

Элементами списка могут быть другие структурированные типы, длину которых также можно вычислить. Длина этих элементов не учитывается в расчёте длины списка:

alist = ["Привет", 2.0, 5]
print(len(alist))
print(len(alist[0]))

      
alist = ["Привет", 2.0, 5]
print(len(alist))
print(len(alist[0]))

В этом примере функция len(alist) вернёт число x ? , а вызов функции len(alist[0]) вернёт число x , так как мы находим длину элемента под индексом 0.

Что выведется на экран после выполнения следующей программы:

alist = [3, 67, "кот", 3.14, [True, False]]
print(len(alist))

Верно. Список [True, False] считается за один элемент списка alist.

Функция len() возвращает не индекс последнего элемента, а их количество.

Список [True, False] будет считаться за один элемента списка alist.

Код записан корректно.

Оператор получения среза

Чтобы получить часть списка используется оператор среза [:]. Со списками оператор среза работает также, как и для строковых значений:

a_list = ['а', 'б', 'в', 'г', 'д', 'е']
print(a_list[1:3])
print(a_list[:4])
print(a_list[3:])
print(a_list[:])

      
a_list = ['а', 'б', 'в', 'г', 'д', 'е']
print(a_list[1:3])
print(a_list[:4])
print(a_list[3:])
print(a_list[:])

Запустите код примера, чтобы увидеть результат работы оператора [:]. В этом примере чтобы получить срез из первых двух элементов списка нужно записать x a_list[:3].

 

Что выведется на экран после выполнения следующей программы:

alist = [3, 67, "кот", [56, 57, "Python"], [ ], 3.14, False]
print(alist[4:])

Верно. Мы получает срез элементов начиная с индекса 4 и до последнего индекса списка alist.

В срезе не указан последний индекс после :, значит мы берём все элементы до конца списка alist.

Индекс первого элемента равен 0.

Что выведется на экран после выполнения следующей программы:

L = [0.34, '6', 'Курс', 'Python', -2]
print(len(L[1:-1]))

Да, в этом срезе три элемента.

Срез начинается со второго элемента списка L и заканчивается предпоследним элементом.

Срез начинается со второго элемента списка L и заканчивается предпоследним элементом.

Срез начинается со второго элемента списка L и заканчивается предпоследним элементом.

Сложение и умножение

Списки можно складывать между собой. Сложим два списка получим новый список, содержащий элементы первого и второго списка:

odd_list = [1, 3, 5]
even_list = [2, 4, 6]
new_list = odd_list + even_list
print(new_list)

      
odd_list = [1, 3, 5]
even_list = [2, 4, 6]
new_list = odd_list + even_list
print(new_list)

Умножая список на целое число получим новый список в котором элементы исходного списка повторяются заданное количество раз:

zeroes = [0] # список из одного элемента равного 0
lst = zeroes * 5
print(lst)

      
zeroes = [0] # список из одного элемента равного 0
lst = zeroes * 5
print(lst)

После выполнения этого кода список lst будет содержать x элементов, равных нулю.

 

Что выведется на экран после выполнения следующей программы:

alist = [1,3,5]
blist = [2,4,6]
print(alist + blist)

Да, новый список содержит элементы списка alist и следующие за ними элементы списка blist.

Сложение списков не равно сумме длин списков.

Сложение списков не меняет порядка элементов в новом списке.

Сложение списков не складывает между собой элементы этих списков.

Что выведется на экран после выполнения следующей программы:

alist = [1,3,5]
print(alist * 3)

Да, в новом списки элементы исходного списка повторяются указанное количество раз.

В результате умножения списка на число мы не умножаем длину списка на это число.

Умножение не приведёт к повторению каждого элемента по отдельности.

Умножение списка на число не приводит к умножению каждого элемента списка на это число.

Оператор принадлежности in

С помощью операторов in и not in можно определить есть ли в списке указанный элемент:

lang = ["Python", "JavaScript", "C++"]
print("Python" in lang)
print("Java" not in lang)

      
lang = ["Python", "JavaScript", "C++"]
print("Python" in lang)
print("Java" not in lang)

Разбиение и слияние строк

Два метода класса str тесно связаны с использованием списков.

С помощью метода split() можно разделить строку и получить список подстрок. Разделитель по умолчанию - пробел. Но в скобках можно указать произвольную строку-разделитель. Сам разделитель из строки удаляется.

Рисунок 2: Работа метода split()
verse = "Кто понял жизнь тот больше не спешит"
wds = verse.split()
print(wds)

      
verse = "Кто понял жизнь тот больше не спешит"
wds = verse.split()
print(wds)

После выполнения этого кода в переменной wds окажется список содержащий x ? элементов.

Метод split() принимает в качестве аргумента разделитель строки:

verse = "Кто понял жизнь тот больше не спешит"
wds = verse.split("т") # разделитель - буква т
print(wds)

      
verse = "Кто понял жизнь тот больше не спешит"
wds = verse.split("т") # разделитель - буква т
print(wds)

Метод класса join() работает в обратную сторону. С его помощью элементы списка можно соединить в одну строку.

Рисунок 3: Работа метода join()

Запустите следующий код, чтобы увидеть работу метода join():

wds = ["Красота", "спасёт", "мир"]
glue = ';'
s = glue.join(wds)
print(s)
print(wds)

print("***".join(wds))
print("".join(wds))

      
wds = ["Красота", "спасёт", "мир"]
glue = ';'
s = glue.join(wds)
print(s)
print(wds)

print("***".join(wds))
print("".join(wds))

Методы класса list

Класс list содержит ряд методов для изменения списка:

Таблица 1: Некоторые методы класса list
Метод Назначение
<список>.append(x) Добавление x в конец списка
<список>.sort() Сортировка списка
<список>.reverse() Расположение элементов списка в обратном порядке
<список>.index(x) Получение индекса первого вхождения x
<список>.insert(i, x) Вставка в список элемента x по индексу i
<список>.count(x) Получение количества повторений x в списке
<список>.remove(x) Удаление первого вхождения x в список
<список>.pop()
<список>.pop(i)
Удаление из списка последнего или i-го элемента и возврат его значения

Рассмотрим пример применения некоторых методов:

q = [] # создаём пустой список
print(q)

# добавляем к списку два элемента
q.append("курсовая.doc")
q.append("фото.jpg")
print(q)

last = q.pop() # удаляем последний элемент списка
print("Последний элемент:", last)
print(q)

q.insert(0, "!ДИПЛОМ.docx") # вставляем элемент в начало списка
print(q)

      
q = [] # создаём пустой список
print(q)

# добавляем к списку два элемента
q.append("курсовая.doc")
q.append("фото.jpg")
print(q)

last = q.pop() # удаляем последний элемент списка
print("Последний элемент:", last)
print(q)

q.insert(0, "!ДИПЛОМ.docx") # вставляем элемент в начало списка
print(q)

Если мы захотим удалить из списка q первый элемент то запишем инструкцию x q.pop(0).

Операторы обработки списков собраны в следующей таблице:

Таблица 2: Инструкции и операторы для обработки списков
Инструкции и операторы Значение
+ Конкатенация
* Повторение
<список>[] Индексирование
<список>[: ] Срез
len(<список>) Количество элементов
for <элемент> in <список> Перебор символов
<выражение> in <список> Проверка принадлежности (Boolean)
Тип данных Кортеж

В Python есть ещё один последовательный тип данных - кортеж (тип tuple). В отличие от списков, содержимое кортежа нельзя редактировать после создания:

data = (1, 2, 3)    # создание кортежа
print(data[0])      # обращение к элементу кортежа по индексу
data[0] = 0         # возникнет ошибка!

      
data = (1, 2, 3)    # создание кортежа
print(data[0])      # обращение к элементу кортежа по индексу
data[0] = 0         # возникнет ошибка!

Кортежи в Python имеют несколько применений: одновременное присваивание, возврат нескольких значений из функции, передача аргументов в функции и др.

Подробнее с кортежами можно познакомиться по ссылке.

Примеры

Пример № 1 (ex01.py)

Дано 5 целых чисел вводимых с клавиатуры. Напишите программу, которая определяет наименьшее из введённых чисел и выводит его на экран.

data = [] 
print("Введите 5 чисел") 

for i in range(5): 
    n = int(input('> ')) 
    data.append(n) # добавляем число к списку

print("Список значений: ", data) 
min = data[0] 
for x in data: 
    if x < min: 
        min = x

print("Минимальное значение: ", min) 

      
data = [] 
print("Введите 5 чисел") 

for i in range(5): 
    n = int(input('> ')) 
    data.append(n) # добавляем число к списку

print("Список значений: ", data) 
min = data[0] 
for x in data: 
    if x < min: 
        min = x

print("Минимальное значение: ", min) 

Список оценок будет храниться в переменной с именем x . С помощью цикла попросим пользователя пять раз ввести с клавиатуры оценку и сохраним её в переменную n. Затем с помощью метода списка append() добавим оценку в конец списка.

В девятой строке программы переменной min присвоим x первый элемент списка data. Цикл for в десятой строке позволит перебрать все элементы списка и сравнить каждый элемент со значением в переменной min.

Пример № 2 (ex02.py)

Дан список из 10 случайных целых чисел в отрезке 0, 20. Отсортируйте список по возрастанию и убыванию и выведите результаты на экран. Для решения используйте стандартные методы для списков.

import random 

data = [] 

for i in range(10): 
    n = random.randint(0, 20) 
    data.append(n) # добавляем число к списку

data.sort() # сортируем список
print(data) 
data.reverse() # инвертируем порядок элементов
print(data) 

      
import random 

data = [] 

for i in range(10): 
    n = random.randint(0, 20) 
    data.append(n) # добавляем число к списку

data.sort() # сортируем список
print(data) 
data.reverse() # инвертируем порядок элементов
print(data) 

Пример № 3 (ex03.py)

Пользователь вводит строку, которая содержит ASCII-коды, разделённые пробелом. Программа выводит на экран расшифрованное сообщение.

inString = input("Введите сообщение: ")
message = [] # создаём пустой список

codes = inString.split(" ") # получаем список "чисел"

# перебираем все "числа" из кода
for numStr in codes:
    # преобразуем строку в число
    codeNum = int(numStr)
    # добавляем раскодированный символ к итоговому сообщению
    message.append(chr(codeNum))

# получаем из списка букв одну строку
messageStr = "".join(message)
print(f"Текст сообщения: {messageStr}")

      
inString = input("Введите сообщение: ")
message = [] # создаём пустой список

codes = inString.split(" ") # получаем список "чисел"

# перебираем все "числа" из кода
for numStr in codes:
    # преобразуем строку в число
    codeNum = int(numStr)
    # добавляем раскодированный символ к итоговому сообщению
    message.append(chr(codeNum))

# получаем из списка букв одну строку
messageStr = "".join(message)
print(f"Текст сообщения: {messageStr}")

Раскодируйте сообщение, скрытое в этом коде:

90 110 97 110 105 101 32 45 32 115 105 108 97 33

Задания для самостоятельной работы

Задание № 1 (sam01.py)

Пользователь вводит целое число n - количество элементов в списке. Затем программа просит пользователя ввести n чисел и сохраняет их в списке. Вывести на экран только чётные числа, хранящиеся в списке.

Пример:

Введите количество чисел (n): 4
Введите число: 2
Введите число: 1
Введите число: 7
Введите число: 8
Чётные числа:
2
8

Для определения чётности числа пригодится оператор получения остатка от деления %. Если остаток деления на 2 равен нулю, значит число чётное.

Решение может содержать два цикла for. Один для ввода чисел, второй - для поиска и вывода чётных чисел.

# ввод количества чисел n
n = int(input("Введите количество чисел (n): "))

# создаём пустой список lst
lst = []

# запускаем цикл for, который выполнится n раз
for i in range(n):
    num = int(input("Введите число: "))
    # добавляем введёное число в список lst
    lst.append(num)

print(lst)
print("Чётные числа:")
for i in lst:
    if i % 2 == 0:
        print(i)

Задание № 2 (sam02.py)

Пользователь вводит целое число n - количество элементов в списке. Программа создаёт список из n случайных чисел из диапазона от -10 до 10 и выводит их на экран. После этого выведите на экран элементы списка стоящие на позициях с чётными номерами.

Дополнительный плюс, если не будет использован оператор if.

Пример:

Введите количество чисел (n): 4
Содержимое списка: [-6, -2, 5, -8]
Числа с чётными номерами:
-6
5

Задание № 3 (sam03.py)

Два друга попросили помочь вам с покупками. Каждый из них прислал вам свой список продуктов (3 продукта). Разработайте программу которая позволит ввести в две отдельные переменные списки продуктов, соединит эти списки и отсортирует общий список по алфавиту. Отсортированный список должен быть выведен на экран следующим образом:

  • каждый элемент с новой строки;
  • каждый элемент пронумерован по-порядку.

Пример:

Введите продукты из первого списка (3 шт.)
молоко
хлеб
шоколадка
Введите продукты из второго списка (3 шт.)
масло
пельмени
макароны
Общий список: ['молоко', 'хлеб', 'шоколадка', 'масло', 'пельмени', 'макароны']
1. макароны
2. масло
3. молоко
4. пельмени
5. хлеб
6. шоколадка

Задание № 4 (sam04.py)

Вам дали задание найти максимальную и минимальную оценку за тест. Программа просит пользователя ввести n - количество оценок. После этого программа просит ввести n оценок. В итоге программа выводит максимальную и минимальную оценку.

Пример:

Введите количество оценок: 5
Введите оценку: 6
Введите оценку: 7
Введите оценку: 4
Введите оценку: 4
Введите оценку: 5
Максимальная оценка: 7, минимальная оценка: 4

Задание № 5 (sam05.py)

Создайте программу, которая создаёт аббревиатуру по введённым словам. Буквы в аббревиатуре должны быть большими.

Примеры:

Введите строку: запоминающее устройство
Аббревиатура: ЗУ
Введите строку: открытое акционерное общество
Аббревиатура: ОАО
Введите строку: Белорусский Государственный Педагогический Университет
Аббревиатура: БГПУ

Задание № 6 (sam06.py)

Пользователь вводит целое число n - количество элементов в списке. Затем программа просит пользователя ввести n чисел и сохраняет их в списке. Программа формирует новый список в котором сначала идут положительные, затем отрицательные числа исходного списка. Порядок положительных и отрицательных чисел должен совпадать с порядком в оригинальном списке. Выведите новый список на экран.

Уведомление

Исходные числа должны быть переставлены либо в исходном списке, либо расположены в новом списке.

Пример:

Введите количество чисел: 5
Введите оценку: -2
Введите оценку: -5
Введите оценку: 9
Введите оценку: -7
Введите оценку: 5
Ответ: [9, 5, -2, -5, -7]

Задание № 7 (sam07.py)

Пользователь вводит текст. Программа рассчитывает среднюю длину слов и выводит её на экран.

Пример:

Введите текст: Они работали в институте, который занимался прежде всего проблемами 
человеческого счастья и смысла человеческой жизни, но даже среди них никто точно не знал, 
что такое счастье и в чём именно смысл жизни. И они приняли рабочую гипотезу, что счастье 
в непрерывном познании неизвестного и смысл жизни в том же.
Средняя длина слова в тексте: 5.29
Форматированный вывод

Для того чтобы вывести определённое количество знаков после запятой в вещественных числах, используйте f-строки с таким форматом:

f"{3.1415:0.2f}"

Число после точки определяет количество знаков после запятой.