На этом шаге мы рассмотрим особенности реализации таких вычислений.
Вы хотите проводить различные вычисления (например, поиск минимального и максимального значений, сортировку) на словаре с данными.
Рассмотрим словарь, который отображает тикеры (идентификаторы акций на бирже) на цены:
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
Чтобы выполнить вычисления на содержимом словаря, часто бывает полезно обратить ключи и значения, используя функцию zip(). Например, вот так можно найти минимальную и максимальную цены, а также соответствующий тикер:
min_price = min(zip(prices.values(), prices.keys())) # min_price - (10.75, 'FB') max_price = max(zip(prices.values(), prices.keys())) # max_price - (612.78, 'AAPL')
Похожим образом для ранжирования данных можно использовать zip() с sorted(), как показано ниже:
prices_sorted = sorted(zip(prices.values(), prices.keys())) # prices_sorted - [(10.75, 'FB'), (37.2, 'HPQ'), # (45.23, 'ACME'), (205.55, 'IBM'), # (612.78, 'AAPL')]
Когда вы производите эти вычисления, обратите внимание, что zip() создает итератор, по которому можно пройти только один раз. Например, следующий фрагмент кода - неправильный:
prices_and_names = zip(prices.values(), prices.keys()) print(min(prices_and_names)) # OK print(max(prices_and_names)) # ValueError: max() arg is an empty sequence
Если вы попытаетесь выполнить обычные функции обработки данных на словаре, то обнаружите, что они обрабатывают лишь ключи, но не значения. Например:
min(prices) # Вернет 'AAPL' max(prices) # Вернет 'IBM'
Вероятно, это не то, чего вы хотели добиться, поскольку пытались выполнить вычисления с использованием значений словаря. Вы можете попробовать исправить это, используя метод словаря values():
min(prices.values()) # Вернет 10.75 max(prices.values()) # Вернет 612.78
К несчастью, в большинстве случаев это не то, чего вы хотите. Например, вам нужно знать соответствующие ключи (т. е. понять, у каких акций самая низкая цена).
Вы можете получить ключ, соответствующий минимальному или максимальному значению, если передадите функцию в функции min() и max(). Например:
min(prices, key=lambda k: prices[k]) # Вернет 'FB' max(prices, key=lambda k: prices[k]) # Вернет 'AAPL'
Однако чтобы получить минимальное значение, вам потребуется дополнительное обращение. Например:
min_value = prices[min(prices, key=lambda k: prices[k])]
Использование функции zip() решает задачу путем "обращения" словаря в последовательность пар (value, key). Когда выполняется сравнение таких кортежей, элемент value сравнивается первым, а key - следующим. Это дает вам то самое поведение, которое вы хотите, а также позволяет проводить обработки и сортировку словаря с использованием единственного выражения.
Стоит отметить, что в вычислениях с использованием пар (value, key) будет применен key, чтобы определить результат в экземплярах, где множественные записи имеют одинаковые value. Например, в вычислениях min() и max() запись с наименьшим или наибольшим ключом будет возвращена, если найдутся одинаковые значения. Например:
>>> prices = {'AAA': 45.23, 'ZZZ': 45.23}
>>> min(zip(prices.values(), prices.keys()))
(45.23, 'AAA')
>>> max(zip(prices.values(), prices.keys()))
(45.23, 'ZZZ')
>>>
На следующем шаге мы рассмотрим поиск общих элементов в двух словарях.