Со списками, так же как и со строками, можно делать срезы. А именно:
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, ...)))
Если каждый элемент списка определяется по достаточно простой формуле (или выражается достаточно простым образом через элементы другого списка), то для его создания удобно использовать генераторы списков (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)**2for d in str(my_num)])
В питоне True и False можно использовать как числа в арифметических выражениях.
Истина равна единице, а ложь — нулю.
Это позволяет писать кратко некоторые вещи.
Например, пусть у нас есть числа a, b, c, и мы хотим узнать, сколько из них больше нуля.
Вместо громоздкой конструкции
res = 0if a > 0:
res += 1if b > 0:
res += 1if 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 = 0for i in range(1, 10000):
str_i = str(i)
if'7'in str_i:
nums_with_7 += 1
print(nums_with_7)
Первая строка — считывание данных.
Вторая строка — создание списка.
Третья строка — цикл for.
Четвертая строка — добавление нового элемента в список.
Пятая строка — вывод результата.
Для суммирования среза списка используйте функцию sum.
Первая строка — считывание списка.
Вторая строка — цикл for и считывание числа повторений.
Третья строка — модификация списка в цикле.
Четвертая строка — вывод результата.
Иногда бывает нужно проверить, если в списке хотя бы один какой-нибудь «особый» элемент.
Или проверить, что все элементы списка «хорошие».
Команды all и any позволяют сделать это в одну строчку.
Итак, если имеется какой-нибудь итерируемый объект (например, список), то выражение
all(условие for объект in что-то_итерируемое)
принимает значение True если и только если, условие выполнено для всех объектов в что-то_итерируемое.
any(условие for объект in что-то_итерируемое)
принимает значение True если и только если, условие выполнено хотя бы для одного объекта в что-то_итерируемое.
Например, проверим, что все числа в списке (или хотя бы одно) находятся в диапазоне от 1000 до 9999:
if all(1000 <= x <= 9999for x in my_list):
print('Все элементы от 1000 до 9999')
if any(1000 <= x <= 9999for x in my_list):
print('По крайней мере один элемент от 1000 до 9999')
Развёрнутый код для каждой из конструкций:
bad_found = Falsefor x in my_list:
ifnot1000 <= x <= 9999:
bad_found = Truebreakifnot bad_found:
print('Все элементы от 1000 до 9999')
#
good_found = Falsefor x in my_list:
if1000 <= x <= 9999:
good_found = Truebreakif good_found:
print('По крайней мере один элемент от 1000 до 9999')
В языке питон есть тернарная условная операция, подобная [expression]?[on_true]:[on_false] в языке си.
Тернарная условная операция принимает на вход три параметра: логическое выражение и два значения,
и возвращает первое или второе значение в зависимости от значения логического выражения.
Его синтаксис такой:
Билет с шестизначным номером называется «счастливым», если сумма первых трёх цифр совпадает с суммой трёх последних.
Посчитайте количество счастливых билетов.
Решите эту задачу в одну строчку
Если бы мы считали четырёхзначные билеты, то ответ был бы таким:
Дан список чисел. Переставьте его элементы следующим образом. Элементы с чётными индексами (0, 2, 4, ...)
остаются на своих местах, а элементы с нечётными индексами меняют свой порядок на противоположный.
Выведите полученный список после модификации.
Решите эту задачу в три строчки. Первая строка — считывание списка,
вторая строка — модификация списка, третья строка — вывод результата.
Дан список чисел. Разделите его на две равные части и переставьте эти части местами,
не меняя порядка элементов внутри одной части. Если в списке нечётное число элементов,
то средний элемент остаётся на своём месте.
Выведите полученный список после модификации.
Решите эту задачу в три строчки. Первая строка — считывание списка,
вторая строка — модификация списка, третья строка — вывод результата.