Со списками, так же как и со строками, можно делать срезы. А именно:
A[i:j] срез из j-i элементов
A[i], A[i+1], ..., A[j-1].
A[i:j:-1] срез из i-j элементов
A[i], A[i-1], ..., A[j+1]
(то есть меняется порядок элементов).
A[i:j:k] срез с шагом k:
A[i], A[i+k], A[i+2*k],... .
Если значение k<0, то элементы идут в противоположном порядке.
Каждое из чисел i или j может отсутствовать,
что означает «начало строки» или «конец строки»
Списки, в отличии от строк, являются изменяемыми объектами:
можно отдельному элементу списка присвоить новое значение. Но можно менять и целиком
срезы. Например:
A = [1, 2, 3, 4, 5]
A[2:4] = [7, 8, 9]
Получится список, у которого вместо двух элементов среза A[2:4]
вставлен новый список уже из трех элементов. Теперь список стал равен
[1, 2, 7, 8, 9, 5].
Получится список [40, 2, 30, 4, 20, 6, 10]. Здесь
A[::-2] — это список из элементов
A[-1], A[-3], A[-5], A[-7],
которым присваиваются значения 10, 20, 30, 40 соответственно.
Если не непрерывному срезу (то есть срезу с шагом k, отличному
от 1), присвоить новое значение, то количество элементов в старом и новом срезе
обязательно должно совпадать, в противном случае произойдет ошибка ValueError.
Обратите внимание, A[i] — это элемент списка, а не срез!
Упражнения
Большинство упражнений этого листка копирует задачи предыдущего листка.
Но в предыдущем листке задачи необходимо решать без использования срезов, дополнительных списков, методов списков.
В этом же листке, наоборот, нельзя использовать циклы. Используйте срезы и методы.
Для многих упражнений написано, какое наибольшее число строк может быть в программе.
Как правило, ограничения будут или в одну строку, или в три строки.
Если программа решается в одну строку, то необходимо использовать функции внутри функций.
Например, вот так можно вычислить сумму всех чисел, введенных в строку, используя стандартную функцию sum:
print(sum(map(int, input().split())))
Обратите внимание, в однострочном решении нельзя сохранять список в переменной - нужно сразу же его обработать и
вывести результат.
Решение в две строки, как правило, должно иметь следующий вид:
A = input().split()
print(' '.join(...))
При этом зачастую не требуется преобразовывать элементы списка к типу int.
Решение в три строки, как правило, должно иметь следующий вид:
A = input().split()
A = ...
print(' '.join(map(str, ...)))
A: Четные индексы
Выведите все элементы списка с четными индексами
Решите эту задачу в одну строку
1 2 3 4 5
1 3 5
IDE
Генераторы списков — 2
Если каждый элемент списка определяется по достаточно простой формуле (или выражается достаточно простым образом через элементы другого списка), то для его создания удобно использовать генераторы списков (list comprehension): выражения, позволяющие заполнить список некоторой формулой.
Общий вид генератора следующий:
[ выражение for переменная in что-то_итерируемое]
Также генератор может быть усложнён, если добавить дополнительное условие:
[ выражение for переменная in что-то_итерируемое if что_проверить]
Здесь переменная — идентификатор некоторой
переменной; что-то_итерируемое — итерируемый объект, из которого извлекаются значения (например, список или range);
выражение — некоторое выражение, которым будут заполнены
элементы списка, как правило, зависящее от использованной в генераторе переменной;
что_проверить — необязательное условие, выполнение которого необходимо для того, элемент был добавлен.
Например, если нужно выбрать все числа, делящиеся на 7 в некотором списке, то это можно сделать так:
my_list = [10, 53, 14, 53, 88, 43, 89, 84, 41, 21, 25, 25, 63, 74, 50, 72, 18, 57, 59, 92]
nums_0_mod_7 = [x for x in my_list if x % 7 == 0]
# Если нужно их сразу вывести:
print(' '.join([str(x) for x in my_list if x % 7 == 0]))
Кстати, каждая строка является итерируемым объектом, который по очереди возвращает свои цифры.
Сумму квадратов цифр числа можно найти так:
my_num = 549523521596
sum_dig_sq = sum([int(d)**2 for d in str(my_num)])
B: Четные элементы
Выведите все четные элементы списка.
Решите эту задачу в одну строку
1 2 2 3 3 3 4
2 2 4
IDE
Суммируем логические выражения
В питоне True и False можно использовать как числа в арифметических выражениях.
Истина равна единице, а ложь — нулю.
Это позволяет писать кратко некоторые вещи.
Например, пусть у нас есть числа a, b, c, и мы хотим узнать, сколько из них больше нуля.
Вместо громоздкой конструкции
res = 0
if a > 0:
res += 1
if b > 0:
res += 1
if c > 0:
res += 1
можно написать коротко
res = (a > 0) + (b > 0) + (c > 0)
Вместе с генератором списка эта возможность позволяет подсчитывать количество «хороших» элементов в списке в одну строчку.
Например, можно так можно посчитать количество чисел от 1 до 9999, в десятичной записи которых есть цифра 7:
print(sum(['7' in str(i) for i in range(1, 10000)]))
Как это работает? Конструкция '7' in str(i) возвращает True, если цифра 7 есть в записи числа i, и False иначе. При этом число i пробегает все значения от 1 до 9999: ('7' in str(i) for i in range(1, 10000)). И наконец функция sum вычисляет сумму всех этих выражений. Так как False равен 0, то сумма равна в точности количеству чисел от 1 до 9999, в десятичной записи которых есть цифра 7.
Развёрнутый код для этой конструкции получается таким:
nums_with_7 = 0
for i in range(1, 10000):
str_i = str(i)
if '7' in str_i:
nums_with_7 += 1
print(nums_with_7)
C: Количество положительных
Найдите количество положительных элементов в данном списке.
Решите эту задачу в одну строку
1 -2 3 -4 5
3
IDE
Операции со списками
Со списками можно легко делать много разных операций.
x in A
Проверить, содержится ли элемент в списке. Возвращает True или False
x not in A
То же самое, что not(x in A)
min(A)
Наименьший элемент списка
max(A)
Наибольший элемент списка
A.index(x)
Индекс первого вхождения элемента x в список, при его отсутствии генерирует исключение ValueError
A.count(x)
Количество вхождений элемента x в список
A.append(x)
Добавить в конец списка A элемент x.
A.insert(i, x)
Вставить в список A элемент x
на позицию с индексом i. Элементы списка A,
которые до вставки имели индексы i и больше сдвигаются
вправо.
A.extend(B)
Добавить в конец списка A содержимое списка B.
A.pop()
Удалить из списка последний элемент, возвращается значение удаленного элемента
A.pop(i)
Удалить из списка элемент с индексом i,
возвращается значение удаленного элемента. Все элементы, стоящие
правее удаленного, сдвигаются влево.
F: Наибольший элемент
Решите эту задачу в две строки
1 2 3 2 1
3 2
IDE
H: Наименьший положительный
Выведите значение наименьшего из всех положительных элементов в списке.
Известно, что в списке есть хотя бы один положительный элемент.
Решите эту задачу в одну строчку.
5 -4 3 -2 1
1
IDE
M: Вывести в обратном порядке
Решите эту задачу в одну строку.
(Требуется только вывести входные числа в обратном порядке, а не переставлять элементы списка.)
Решите эту задачу в две строки.
Требуется только вывести циклический сдвиг входных данных, а не переставлять список.
1 2 3 4 5
5 1 2 3 4
IDE
X: Числа k-боначчи
Решите эту задачу в пять строк.
Первая строка — считывание данных.
Вторая строка — создание списка.
Третья строка — цикл for.
Четвертая строка — добавление нового элемента в список.
Пятая строка — вывод результата.
Для суммирования среза списка используйте функцию sum.
3 6
17
100 0
1
IDE
Y: Кузнечики
Решите эту задачу в четыре строки
Первая строка — считывание списка.
Вторая строка — цикл for и считывание числа повторений.
Третья строка — модификация списка в цикле.
Четвертая строка — вывод результата.
1 2 3 4 2
2
4 1 2 2 3
IDE
Проверки all и any
Иногда бывает нужно проверить, если в списке хотя бы один какой-нибудь «особый» элемент.
Или проверить, что все элементы списка «хорошие».
Команды all и any позволяют сделать это в одну строчку.
Итак, если имеется какой-нибудь итерируемый объект (например, список), то выражение
all(условие for объект in что-то_итерируемое)
принимает значение True если и только если, условие выполнено для всех объектов в что-то_итерируемое.
any(условие for объект in что-то_итерируемое)
принимает значение True если и только если, условие выполнено хотя бы для одного объекта в что-то_итерируемое.
Например, проверим, что все числа в списке (или хотя бы одно) находятся в диапазоне от 1000 до 9999:
if all(1000 <= x <= 9999 for x in my_list):
print('Все элементы от 1000 до 9999')
if any(1000 <= x <= 9999 for x in my_list):
print('По крайней мере один элемент от 1000 до 9999')
Развёрнутый код для каждой из конструкций:
bad_found = False
for x in my_list:
if not 1000 <= x <= 9999:
bad_found = True
break
if not bad_found:
print('Все элементы от 1000 до 9999')
#
good_found = False
for x in my_list:
if 1000 <= x <= 9999:
good_found = True
break
if good_found:
print('По крайней мере один элемент от 1000 до 9999')
Тернарный оператор условия
В языке питон есть тернарная условная операция, подобная [expression]?[on_true]:[on_false] в языке си.
Тернарная условная операция принимает на вход три параметра: логическое выражение и два значения,
и возвращает первое или второе значение в зависимости от значения логического выражения.
Его синтаксис такой:
[on_true] if [expression] else [on_false]
>>> 'equal' if 1 == 1 else 'not equal'
'equal'
>>> 'equal' if 1 == 2 else 'not equal'
'not equal'
Данную конструкцию можно вкладывать в себя:
res = 'foo' if x == 1 else 'boo' if x == 2 else 'zoo' if x == 3 else 'goo'
Ситуация, когда тернарный оператор прямо уместен, встречается не так часто.
Однако в генераторах списков, в all и в any он может быть удобен.
ZA: Числа с 0 в десятичной записи
На вход даётся натуральное число $N < 1000000$.
Выведите количество чисел от 1 до $N$, в десятичной записи которых есть цифра 0.
Решите эту задачу в одну строчку
9
0
10
1
1000
181
IDE
ZB: Количество нулей в десятичной записи
На вход даётся натуральное число $N < 1000000$.
Выведите количество цифр 0, которые встречаются в десятичной записи чисел от 1 до $N$.
Решите эту задачу в одну строчку
9
0
10
1
1000
192
IDE
ZC: Счастливые билеты
Билет с шестизначным номером называется «счастливым», если сумма первых трёх цифр совпадает с суммой трёх последних.
Посчитайте количество счастливых билетов.
Решите эту задачу в одну строчку
Если бы мы считали четырёхзначные билеты, то ответ был бы таким:
670
Не забудьте, что 000000 — тоже счастливый билет!
IDE
ZD: Развернуть элементы с нечётными индексами
Дан список чисел. Переставьте его элементы следующим образом. Элементы с чётными индексами (0, 2, 4, ...)
остаются на своих местах, а элементы с нечётными индексами меняют свой порядок на противоположный.
Выведите полученный список после модификации.
Решите эту задачу в три строчки. Первая строка — считывание списка,
вторая строка — модификация списка, третья строка — вывод результата.
9 8 7 6 5 4 3 2
9 2 7 4 5 6 3 8
9 8 7 6 5 4 3 2 1
9 2 7 4 5 6 3 8 1
IDE
ZE: Переставить половинки списка
Дан список чисел. Разделите его на две равные части и переставьте эти части местами,
не меняя порядка элементов внутри одной части. Если в списке нечётное число элементов,
то средний элемент остаётся на своём месте.
Выведите полученный список после модификации.
Решите эту задачу в три строчки. Первая строка — считывание списка,
вторая строка — модификация списка, третья строка — вывод результата.