Шаг 30.
Однострочники Python. Трюки Python. Поиск компаний, платящих меньше минимальной зарплаты, с помощью выражений-генераторов

    На этом шаге нас ожидает комбинация некоторых уже изученных базовых возможностей 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 Гвидо ван Россум (Guido van Rossum), большой поклонник функции any(), даже предложил включить ее в качестве встроенной функции в Python 3.

    Интересное расширение Python, обобщающее списковые включения, - выражения-генераторы. Они работают совершенно аналогично списковым включениям, только без создания в памяти собственно списка. Числа создаются по ходу дела, без сохранения их явным образом в списке. Например, вместо вычисления квадратов первых 20 натуральных чисел с помощью спискового включения, sum([x*x for x in range(20)]), можно воспользоваться выражением-генератором: sum(x*x for x in range(20)).

Код

    Наши данные представляют собой ассоциативный массив ассоциативных массивов, в которых хранятся почасовые ставки работников компаний. Необходимо выделить из него список компаний, платящих по крайней мере одному сотруднику меньше установленной законом минимальной почасовой ставки (< $9) (пример 2.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().




Предыдущий шаг Содержание Следующий шаг