Как выполнить итерацию по словарю в Python - 2 часть
Просто Python | Data science | ML | AIОсновательное знание итерации по словарю поможет вам написать лучший, более надежный код. В вашем путешествии по итерации по словарю вы напишете несколько примеров, которые помогут вам понять различные способы обхода словаря путем перебора его ключей, значений и элементов.
Содержание:
- Обход словаря в отсортированном и обратном порядке
- Перебор отсортированных ключей
- Перебор отсортированных значений
- Сортировка словаря с пониманием
- Выполнение итерации по словарю в порядке обратной сортировки
- Прохождение словаря в обратном порядке
- Деструктивная итерация по словарю с помощью .popitem()
- Использование встроенных функций для неявной итерации по словарям
- Применение преобразования к элементам словаря: map()
- Фильтрация элементов в словаре: filter()
- Просмотр нескольких словарей как одного
- Выполнение итерации по нескольким словарям с помощью ChainMap
- Выполнение итерации по цепочке словарей с помощью chain()
- Перебор объединенных словарей: оператор распаковки (**)

Обход словаря в отсортированном и обратном порядке
Иногда вам может потребоваться выполнить итерацию по словарю в отсортированном порядке. Вы можете сделать это с помощью встроенной функции sorted() . Когда вы вызываете эту функцию с iterable в качестве аргумента, вы получаете list элементов в отсортированном порядке.
Примечание: Чтобы углубиться в сортировку словарей Python, ознакомьтесь с Сортировка словаря Python: значения, ключи и многое другое.
Выполнение итерации по словарю в обратном порядке также может быть распространенным требованием в коде. В этом случае вы можете использовать встроенную reversed() функцию, которая принимает итерируемый параметр в качестве аргумента и выдает его элементы в обратном порядке.
В следующих разделах вы узнаете, как использовать эти инструменты для выполнения итераций по словарю Python в отсортированном и обратном порядке соответственно.
Перебор отсортированных ключей
Если вам нужно выполнить итерацию по ключам словаря в отсортированном порядке, то вы можете передать свой словарь в качестве аргумента в sorted(). Вы получите список, содержащий ключи в отсортированном порядке. Этот список позволит вам просматривать ваш словарь, отсортированный по ключам:
>>>
>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}
>>> for fruit in sorted(incomes):
... print(fruit, "->", incomes[fruit])
...
apple -> 5600.0
banana -> 5000.0
orange -> 3500.0
В этом примере вы сортируете ключи, вызывая sorted() используя свой dictionary в качестве аргумента. Обратите внимание, что вы могли бы также использовать sorted(incomes.keys()) для получения того же результата. В обоих случаях вы получите list содержащий ключи вашего словаря в отсортированном порядке.
Обратите внимание, что порядок сортировки будет зависеть от типа данных ваших ключей и внутренних правил, которые Python использует для сортировки этого конкретного типа данных. В этом примере Python сортирует ключи, используя свои внутренние правила для сортировки строк. Эти правила основаны на символах Unicode кодовые точки. Дальнейшее объяснение этих внутренних правил выходит за рамки данного руководства.
Перебор отсортированных значений
Вам также может потребоваться выполнить итерацию по словарю Python с его элементами, отсортированными по значениям. Для этого вы также можете использовать sorted() . На этот раз вам нужно будет использовать второй аргумент, вызываемый key при вызове sorted(). This аргумент только для ключевых слов задает функцию с одним аргументом для извлечения ключа сравнения из обрабатываемых элементов.
Для выполнения итерации по элементам словаря, отсортированным по значению, вы можете написать функцию, которая возвращает значение каждого элемента, а затем использовать эту функцию в качестве key аргумента для sorted(). В приведенном ниже примере вы делаете это с помощью короткой lambda функции:
>>>
>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}
>>> for fruit, income in sorted(incomes.items(), key=lambda item: item[1]):
... print(fruit, "->", income)
...
orange -> 3500.0
banana -> 5000.0
apple -> 5600.0
В этом примере вы определяете lambda функцию и используете ее для сортировки элементов incomes по значению с помощью sorted(). lambdaФункция сообщает sorted() о необходимости сортировки incomes.items() по второму элементу каждого элемента, item[1], который является значением дохода.
Вы также можете захотеть выполнить итерацию по значениям словаря в отсортированном порядке без учета ключей. В этом случае вы можете использовать .values() для обеспечения дополнения для sorted(). Вот краткий пример:
>>>
>>> for income in sorted(incomes.values()): ... print(income) ... 3500.0 5000.0 5600.0
Вызов sorted() с incomes.values() в качестве аргумента возвращает значения вашего словаря в отсортированном порядке. Помните, что ключи не будут доступны, если вы используете .values(). Все в порядке. Иногда вам не нужны ключи, только значения, и это быстрый способ получить к ним доступ.
Сортировка словаря с пониманием
Что, если вам нужно отсортировать существующий словарь и создать отсортированный? Как вы уже знаете, начиная с Python 3.6, словари запоминают порядок вставки своих элементов. Эта функция позволяет сортировать элементы словаря с помощью sorted() пока вы создаете новый словарь с пониманием:
>>>
>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}
>>> {fruit: incomes[fruit] for fruit in sorted(incomes)}
{'apple': 5600.0, 'banana': 5000.0, 'orange': 3500.0}
>>> {
... fruit: income
... for fruit, income in
... sorted(incomes.items(), key=lambda item: item[1])
... }
{'orange': 3500.0, 'banana': 5000.0, 'apple': 5600.0}
Эти понимания позволяют создавать новые словари с их элементами, отсортированными по ключу и значению соответственно. В обоих случаях понимание выполняет итерацию по исходному словарю в отсортированном порядке и создает новый словарь.
Выполнение итерации по словарю в порядке обратной сортировки
Если вам нужно просмотреть ваши словари в порядке обратной сортировки, то вы можете использовать reverse аргумент для sorted(). Этот аргумент принимает Логическое значение. Если вы используете True, то элементы сортируются в обратном порядке:
>>>
>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}
>>> for fruit in sorted(incomes, reverse=True):
... print(fruit, "->", incomes[fruit])
...
orange -> 3500.0
banana -> 5000.0
apple -> 5600.0
В этом примере вы выполняете итерацию по ключам incomes в порядке обратной сортировки, используя reverse аргумент to sorted() в заголовке вашего for цикла. В этом примере выполняется сортировка ключей. Почему бы вам не попробовать написать пример, который сортирует значения в обратном порядке?
Прохождение словаря в обратном порядке
Другая возможность, которую предлагает Python, когда дело доходит до выполнения итераций по словарям, заключается в использовании встроенной функции reversed() . Эта функция принимает iterable в качестве аргумента и возвращает итератор который выдает элементы в обратном порядке.
Используя reversed(), вы можете просматривать свои словари в обратном порядке:
>>>
>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}
>>> for key, value in reversed(numbers.items()):
... print(key, "->", value)
...
four -> 4
three -> 3
two -> 2
one -> 1
В этом примере вызов to reversed() выдает элементы из numbers в обратном порядке. Это позволяет выполнять итерацию по вашему словарю справа налево, что может быть полезно в некоторых ситуациях.
Деструктивная итерация по словарю с .popitem()
Иногда вам нужно выполнить итерацию по словарю и удалить его элементы после использования. Для выполнения этой задачи вы можете использовать .popitem() метод, который удаляет и возвращает пары ключ-значение из словаря в порядке последнего поступления и первого выхода (LIFO). Когда целевой словарь пуст, то .popitem() возникает KeyError исключение.
Если вам нужно выполнить деструктивную итерацию по словарю в Python, то .popitem() может сделать это за вас:
>>>
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> while True:
... try:
... print(f"Dictionary length: {len(likes)}")
... item = likes.popitem()
... # Do something with the item here...
... print(f"Item {item} removed")
... except KeyError:
... print("Your dictionary is now empty.")
... break
...
Dictionary length: 3
Item ('pet', 'dog') removed
Dictionary length: 2
Item ('fruit', 'apple') removed
Dictionary length: 1
Item ('color', 'blue') removed
Dictionary length: 0
Your dictionary is now empty.
Здесь вы использовали while цикл вместо for loop . Причина этого в том, что небезопасно выполнять итерацию по словарю с помощью for цикла, когда вам нужно удалить элементы из имеющегося под рукой словаря. Вы продолжаете это до тех пор, пока словарь не станет пустым, и .popitem() вызывает KeyError исключение.
Вместо того, чтобы полагаться на обработку исключений, вы можете настроить свой while цикл на словаре, в котором остались элементы:
>>>
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
⏎
>>> while likes:
... print(f"Dictionary length: {len(likes)}")
... item = likes.popitem()
... # Do something with the item here ...
... print(f"Item {item} removed")
...
Dictionary length: 3
Item ('pet', 'dog') removed
Dictionary length: 2
Item ('fruit', 'apple') removed
Dictionary length: 1
Item ('color', 'blue') removed
Переменная item хранит ссылку на текущий элемент, чтобы вы могли выполнять действия с ним на каждой итерации. Цикл прерывается, когда словарь становится пустым, и likes становится ложным. Разницу между этими двумя примерами можно суммировать следующим образом LBYL vs EAFP или, более явно, посмотрите, прежде чем прыгать или проще попросить прощения, чем разрешения.
Использование встроенных функций для неявной итерации по словарям
Python предоставляет некоторые встроенные функции, которые полезны при работе с коллекциями, такими как словари. Эти функции являются своего рода инструментом итерации, поскольку они реализуют внутренний цикл. Из-за их внутреннего цикла вы можете использовать эти функции для неявной итерации по словарю.
В следующих разделах вы изучите две из этих функций: map() и filter(). С помощью map() вы можете применить данное преобразование ко всем элементам в словаре и создать новый. С помощью filter() вы можете извлечь нужные элементы в новый словарь.
Применение преобразования к элементам словаря: map()
map()Функция Python принимает объект function и итерируемый объект в качестве аргументов. Она возвращает итератор, который является результатом применения функции ввода к каждому элементу во входном итерируемом объекте. Вы можете использовать map() выполнять итерацию по словарям в Python, используя преимущества неявного цикла функции.
Допустим, вы хотите применить скидку ко всем товарам в вашем словаре. fruits В этом случае вы можете определить функцию , которая управляет скидкой, а затем использовать эту функцию в качестве первого аргумента для Затем вы можете использовать:............... map(). словарь............... .items() чтобы предоставить итерируемый объект:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}
>>> def apply_discount(product, discount=0.05):
... return product[0], round(product[1] * (1 - discount), 2)
...
>>> dict(map(apply_discount, fruits.items()))
{'apple': 0.38, 'orange': 0.33, 'banana': 0.24}
>>> dict(map(lambda item: apply_discount(item, 0.1), fruits.items()))
{'apple': 0.34, 'orange': 0.3, 'banana': 0.22}
>>> dict(map(lambda item: apply_discount(item, 0.15), fruits.items()))
{'apple': 0.32, 'orange': 0.28, 'banana': 0.2}
В этом фрагменте кода вы определяете функцию с именем apply_discount(), которая применяет скидку к цене данного продукта. Затем она возвращает кортеж, содержащий продукт и его новую цену.
Первый вызов map() выполняет итерацию по элементам словаря, fruits.items() и применяет скидку в размере 5 процентов по умолчанию к каждому фрукту. В этом случае вы используете конструктор dict() для создания нового словаря из данных, которые map() ВОЗВРАТ.
Во втором и третьем вызовах map() вы переносите apply_discount() в lambda функцию, чтобы можно было указать другое значение скидки в apply_discount(). Это распространенный прием, который можно использовать, когда инструмент, подобный map() требуется функция с заданным числом аргументов, а ваша целевая функция не соответствует этому числу.
Фильтрация элементов в словаре: filter()
Встроенная filter() функция - это еще один инструмент, который вы можете использовать для неявной итерации по словарю и фильтрации его элементов в соответствии с заданным условием. Этот инструмент также принимает объект function и iterable в качестве аргументов. Он возвращает итератор из тех элементов входного iterable, для которых функция возвращает True.
Допустим, что вы хотите извлечь товары с ценой ниже, чем 0.40 из вашего fruits словаря. Для этого вы можете определить функцию, которая определяет, удовлетворяет ли цена этому условию, и передать функцию в качестве первого аргумента в filter(). Опять же, вторым аргументом может быть fruits.items(). Вот код для достижения этого:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}
>>> def has_low_price(item, price=0.4):
... return item[1] < price
...
>>> dict(filter(has_low_price, fruits.items()))
{'orange': 0.35, 'banana': 0.25}
Вы выполняете итерацию по элементам fruits с помощью filter(). has_low_price()Функция сравнивает цену товара с целевой ценой и возвращает True если цена товара меньше целевой. В противном случае она возвращает False. В результате вы получаете только те товары, цена которых ниже целевой.
Чтобы указать другую целевую цену, вы можете использовать lambda функцию, как вы делали в предыдущем разделе. Продолжайте и попробуйте.
Просмотр нескольких словарей как одного
collectionsМодули и itertools из Python стандартная библиотека предоставляют пару полезных инструментов, которые позволяют выполнять итерацию по нескольким словарям за один раз.
В разделе collections вы найдете класс ChainMap , который позволяет создавать объект, подобный словарю, путем объединения нескольких существующих словарей. С помощью ChainMap вы можете выполнять итерацию по нескольким словарям, как если бы они были одним.
В разделе itertools вы найдете функцию с именем chain() , которая позволяет выполнять итерацию по нескольким словарям Python по одному за раз.
В следующих разделах вы узнаете, как использовать эти два инструмента для выполнения итерации по нескольким словарям в одном цикле. Вы также узнаете, чем оба инструмента отличаются друг от друга.
Выполнение итерации по нескольким словарям с ChainMap
collectionsМодуль из стандартной библиотеки предоставляет специализированный тип контейнера под названием ChainMap. Это класс, подобный словарю, который вы можете использовать для создания единого обновляемого представления из нескольких существующих словарей. Результирующий объект будет логически отображаться и вести себя как единый словарь.
ChainMap не объединяет входные словари вместе. Вместо этого он сохраняет их во внутреннем списке. Входные словари могут иметь дублирующиеся ключи. Однако в операциях поиска и обновления будет доступен только первый экземпляр дублированного ключа.
Теперь предположим, что у вас есть два словаря, содержащих разные категории товаров и их цены. Вам нужно выполнить итерацию по ним вместе, как по одному словарю. Для достижения этого вы можете создать ChainMap объект и инициализировать его своими словарями:
>>>
>>> from collections import ChainMap
>>> fruits = {"apple": 0.40, "orange": 0.35}
>>> vegetables = {"pepper": 0.20, "onion": 0.55}
>>> catalog = ChainMap(fruits, vegetables)
>>> catalog
ChainMap({'apple': 0.4, 'orange': 0.35}, {'pepper': 0.2, 'onion': 0.55})
>>> for product, price in catalog.items():
... print(product, "->", price)
...
pepper -> 0.2
onion -> 0.55
apple -> 0.4
orange -> 0.35
После импорта ChainMap От collections вам нужно создать ChainMap объект со словарями, которые вы хотите связать в цепочку. Затем вы можете свободно выполнять итерацию по результирующему объекту, как вы бы делали с обычным словарем.
ChainMap объекты имеют тот же интерфейс, что и обычные словари, поэтому вы можете использовать .keys(), values(), и .items() для выполнения итерации по их различным компонентам.
При использовании ChainMap для выполнения итерации по нескольким словарям за один раз вы должны иметь в виду, что если у вас есть дубликаты ключей, то вы сможете получить доступ только к первому из них. Рассмотрим следующий пример:
>>>
>>> from collections import ChainMap
>>> for_adoption = {"dogs": 10, "cats": 7, "pythons": 3}
>>> vet_treatment = {"dogs": 4, "cats": 3, "turtles": 1}
>>> pets = ChainMap(for_adoption, vet_treatment)
>>> for pet, count in pets.items():
... print(pet, "->", count)
...
...
dogs -> 10
cats -> 7
turtles -> 1
pythons -> 3
В этом примере цикл проходил только через первые экземпляры "dogs" и "cats". Следовательно, вы не получаете данные из повторяющихся экземпляров этих ключей.
Выполнение итерации по цепочке словарей с chain()
itertoolsМодуль предоставляет chain() функцию, которая может принимать несколько повторяющихся объектов в качестве аргументов и создавать итератор, который выдает элементы из всех них. Для выполнения своей работы, chain() начинает выдавать элементы из первого итерируемого до исчерпания, затем функция выдает элементы из следующего итерируемого и так далее, пока не будут исчерпаны все входные итерируемые объекты.
Такое поведение позволяет выполнять итерацию по нескольким словарям в цепочке, которая проходит по всем ключам, даже если они повторяются:
>>>
>>> from itertools import chain
>>> for_adoption = {"dogs": 10, "cats": 7, "pythons": 3}
>>> vet_treatment = {"dogs": 4, "cats": 3, "turtles": 1}
>>> pets = chain(for_adoption.items(), vet_treatment.items())
>>> for pet, count in pets:
... print(pet, "->", count)
...
...
dogs -> 10
cats -> 7
pythons -> 3
dogs -> 4
cats -> 3
turtles -> 1
В приведенном выше коде, chain() возвращает итератор, который выдает элементы из for_adoption и vet_treatment. Обратите внимание, что в отличие от ChainMap, функция chain() предоставляет вам доступ ко всем ключам из ваших входных словарей, даже к дублированным.
Перебор по объединенным словарям: оператор распаковки (**)
В Python 3.5 введено обобщение распаковки которое позволяет использовать новый оператор распаковки словаря (**) для объединения нескольких словарей в один. Эта функция позволяет выполнять итерацию по нескольким словарям за один раз:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35}
>>> vegetables = {"pepper": 0.20, "onion": 0.55}
>>> for product, price in {**fruits, **vegetables}.items():
... print(product, "->", price)
...
apple -> 0.4
orange -> 0.35
pepper -> 0.2
onion -> 0.55
Оператор распаковки словаря (**) - потрясающая функция в Python. Она позволяет вам объединять несколько словарей в новый, как вы сделали в примере выше. После объединения словарей вы можете выполнять итерацию по новому словарю, как обычно.
Важно отметить, что если объединяемые словари имеют повторяющиеся или дублирующиеся ключи, то значения самого правого словаря будут преобладать:
>>>
>>> for_adoption = {"dogs": 10, "cats": 7, "pythons": 3}
>>> vet_treatment = {"dogs": 4, "cats": 3, "turtles": 1}
>>> for pet, count in {**for_adoption, **vet_treatment}.items():
... print(pet, "->", count)
...
dogs -> 4
cats -> 3
pythons -> 3
turtles -> 1
В этом примере вместо доступа к первым экземплярам дублирующихся ключей, "dogs" и "cats" вы получаете вторые экземпляры. Такое поведение имеет смысл, потому что первый оператор распаковки создает эти ключи, а второй оператор распаковки обновляет их значения, переопределяя их.
Перевод статьи: Leodanis Pozo Ramos - How to Iterate Through a Dictionary in Python