На этом шаге нас ожидает комбинация некоторых уже изученных базовых возможностей Python, а также знакомство с удобной функцией any().
Представьте, что работаете в инспекции Министерства труда США и хотите найти компании, которые платят меньше минимальной почасовой ставки, чтобы инициировать расследование. Подобно голодным псам у дверцы грузовика с мясом, ваши офицеры, следящие за соблюдением Закона о справедливых условиях труда (Fair Labor Standards Act, FLSA), ждут список компаний, нарушающих закон о минимальной зарплате. Можете ли вы предоставить им такой список?
Вот инструмент, который вам стоит взять на вооружение: функция any() языка Python, принимающая на входе итерируемый объект, например список, и возвращающая True, если вычисление хотя бы одного элемента этого итерируемого объекта дает True. Например, выражение any([True, False, False, False]) равно True, а выражение any([2<1, 3+2>5+5, 3-2<0, 0]) равно False.
Интересное расширение Python, обобщающее списковые включения, - выражения-генераторы. Они работают совершенно аналогично
списковым включениям, только без создания в памяти собственно списка. Числа создаются по ходу дела, без сохранения их явным образом в списке. Например,
вместо вычисления квадратов первых 20 натуральных чисел с помощью спискового включения, sum([x*x for x in range(20)]), можно воспользоваться
выражением-генератором: sum(x*x for x in range(20)).
Наши данные представляют собой ассоциативный массив ассоциативных массивов, в которых хранятся почасовые ставки работников компаний. Необходимо выделить из него список компаний, платящих по крайней мере одному сотруднику меньше установленной законом минимальной почасовой ставки (< $9) (пример 2.9).
## Данные companies = { 'CoolCompany': {'Alice': 33, 'Bob': 28, 'Frank': 29}, 'CheapCompany': {'Ann': 4, 'Lee': 9, 'Chrisi': 7}, 'SosoCompany': {'Esther': 38, 'Cole': 8, 'Paris': 18}} ## Однострочник illegal = [x for x in companies if any(y < 9 for y in companies[x].values())] ## Результат print(illegal)
Деятельность каких компаний необходимо расследовать более подробно?
В этом однострочнике используются два выражения-генератора.
Первое выражение, y<9 for y in companies[x].values(), генерирует входные данные для функции any(). Для каждого сотрудника оно проверяет, не платят ли ему по почасовой ставке ниже минимальной, y<9. Результат представляет собой итерируемый объект значений булева типа. Метод values() ассоциативного массива возвращает хранящуюся в нем коллекцию значений. Например, выражение companies['CoolCompany'].values() возвращает коллекцию почасовых ставок dict_values([33, 28, 29]). Если хотя бы одна из них ниже минимальной, то функция any() вернет True, а название компании будет сохранено в виде строкового значения в итоговом списке illegal, как описано ниже.
Второе выражение-генератор представляет собой списковое включение [x for x in companies if any(...)] и создает список названий компаний, для которых предыдущий вызов функции any() возвращает True. Это и есть компании, платящие своим сотрудникам меньше минимальной почасовой ставки. Обратите внимание, что выражение x in companies обходит все ключи ассоциативного массива: названия компаний 'CoolCompany', 'CheapCompany' и 'SosoCompany'.
Результат, соответственно, будет выглядеть следующим образом:
## Результат print(illegal) # ['CheapCompany', 'SosoCompany']
В двух из трех компаний нужно провести дальнейшее расследование, поскольку они платят слишком мало по крайней мере одному сотруднику. Похоже, вашим офицерам стоит поговорить с Энн, Криси и Коулом!
На следующем шаге мы рассмотрим форматирование баз данных с помощью функции zip().