Перейти к содержанию

Задача №3. Словари и их свойства. Списковое включение

Рекомендации

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

Условие задачи

Внимательно прочтите условие задачи и скопируйте в среду разработки.

# Поиск самых высокооплачиваемых работников

# Дан словарь, в котором нужно найти всех сотрудников, 
# зарабатывающих по крайней мере 100 000 долларов в месяц.

employees = {
    'Alice' : 100000,
    'Bob' : 99817,
    'Carol' : 122908,
    'Frank' : 88123,
    'Eve' : 93121
    }

Словари dict

Вы заметили, что в задаче используется новый тип данных - словари dict. Словарь - это коллекция, в которой неупорядоченно хранятся ключи и связанные с ними элементы.

Достоинством словарей является скорость поиска. Например, чтобы найти элемент в списке, интерпретатору необходимо перебирать элементы до тех пор, пока не попадется искомый элемент. Скорость поиска в словаре постоянна, то есть каждому значению однозначно присвоен один ключ. Словари в Python являются реализацией хеш-таблиц, подробнее о которых вы можете прочитать по ссылке.

Рассмотрим некоторые операции со словарями. Для создания словарей используются фигурные скобки {} внутри которых хранятся пары ключ : значение.

# Примеры словарей
vocabulary = {'а' : 'ананас', 'б' : 'брюква'}
# или с переносом на другие строки
vocabulary = {
    'а' : 'ананас', 
    'б' : 'брюква'
    }

# Пустой словарь
empty_dct = {}
# или
empty_dct = dict()

Словарь является изменяемым типом данных и в него можно добавлять новые ключи. Создадим пустой словарь capitals, который будет хранить страны и столицы.

capitals = {}

# Добавление элементов в словарь
capitals['Россия'] = 'Москва'
capitals['Франция'] = 'Париж'

# обращение к ключу словаря возвращает элемент
print(capitals['Россия'])

Обращение к значению по ключу в словаре похоже на операцию индексации в списках, только вместо числового индекса используется ключ. Ключом может быть любой неизменяемый тип данных, то есть списки, словари и множества ключами быть не могут! Значением может быть любой тип данных.

Рассмотрим полезные методы словарей. Не забывайте, что список методов можно вывести с помощью функции dir().

# получить ключи словаря
capitals.keys()

# получить значения
capitals.values()

# получить пары "ключ:значение"
capitals.items()

# получить значение по ключу "Италия", если такого ключа нет - вернуть "Отсутствует" 
capitals.get('Италия', 'Отсутствует')

# получить значение по ключу 'Италия', если такого ключа нет - добавить в словарь "'Италия':None"
capitals.setdefault('Италия')

Решение

Вариант решения 1

Теперь мы знаем, что для того, чтобы получить значение в словаре, надо обратиться к его ключу. Словарь employees в своих значениях хранит денежные суммы, которые надо сравнить с пороговым значением 100к$.

Воспользуемся циклом for, для того чтобы получить каждый ключ по отдельности через метод словарей keys(). Следовательно, по каждому ключу получим значение, результат сравнения с которым выведем в консоль. Обратите внимание, что вместо i используется name, так как данная переменная лучше отражает суть того, что она хранит.

for name in employees.keys():
    print(f"Для {name} - {employees[name] >= 100000}")

Для двух имен мы получили True: для Alice и Carol. Теперь добавим их в новый список, согласно условию задачи. Для этого опишем фильтрующее условие if и создание и обработку нового списка top_mgrs.

# Пустой список топ-менеджеров
top_mgrs = []

# перебираем ключи и сравниваем значения зп с порогом 100к$
for name in employees.keys():
    if employees[name] >= 100000:
        top_mgrs.append(name)

# вывод в консоль
print(f"Топ-менеджеры: {top_mgrs}")

В результате, мы получаем список сотрудников у которых заработная плата больше 100к$.

Обратите внимание, что решение довольно простое, но занимает несколько строк кода. В следующем параграфе рассмотрим способ записи такого решения короче.

Списковые включения

Если в Python необходимо применить простое фильтрующее условие для обработки списка или словаря, то можно воспользоваться однострочной записью некоторых операторов, например for и if.

Однострочная запись if

Например, имеем следующее условие.

x = 4
if x > 0:
    print("Больше 0")
else:
    print("Меньше 0")

Запись в одну строку выглядит следующим образом.

print("Больше 0" if x > 0 else "Меньше 0")

Выражение для истинного условия записывается слева, а для ложного записывается справа.

Однострочная запись for

Например, имеем список, каждое значение в котором нужно умножить на 2.

lst = [1, 2, 3, 4, 5]
for i in lst:
    print(i * 2)

Запись в одну строку выглядит следующим образом.

print([i*2 for i in [1, 2, 3, 4, 5]])

В данном случае:

  • for i in [1, 2, 3, 4, 5] - цикл, который перебирает числа в списке,
  • i*2 - выражение, которое надо выполнить каждого i из цикла,
  • [ ... ] - список, внутри которого происходят вложенные операции,
  • print() - функция, которая выводит результат в консоль.

Списковые включения list comprehension - это сокращенная запись для обработки списков по заданному условию. Список как бы "генерируется внутри" из исходного списка. Также существуют словарные сборки и генераторные сборки - сокращенные записи на основе словарей и кортежей, соответственно.

Ниже приведены примеры применения списковых включений.

# Создание списка квадратов чисел
squares = [x**2 for x in range(10)]
print(squares)

# Выборка нечетных чисел в заданном диапазоне:
odds = [x for x in range(10) if x%2 != 0]
print(odds)

Вариант решения 2

Рассмотрим однострочный вариант решения задачи про сотрудников. Запишем списковое включение, которое перебирает все ключи словаря employees.

top_mgrs = [n for n in employees]
print(top_mgrs)

Обратите внимание, что ключи из employees можно получить без применения метода keys(). Переменная n - это сокращение от name, так как решение, представленое в одну строку, ограничено по длине используемых переменных.

Добавим условие if в записанное списковое включение. Такие условие записываются после for!

top_mgrs = [n for n in employees if employees[n]>=100000]
print(top_mgrs)

Из словаря можно получить пары ключ:значение используя метод item(), что позволит убрать обращение по ключу. Таким образом однострочное решение будет выглядеть следующим образом.

# списковое включение перебирает ключи и сравниваем значения зп с порогом 100к$
top_mgrs = [n for n,s in employees.items() if s>=100000]

# вывод в консоль
print(f"Топ-менеджеры: {top_mgrs}")

В результате, мы получаем список сотрудников у которых заработная плата больше 100к$.