#python #python-2.7 #python-3.x
#python #python-2.7 #python-3.x
Вопрос:
Я пытаюсь получить значение из многомерного словаря, который выглядит, например, так:
count = {'animals': {'dogs': {'chihuahua': 23}}
Итак, если я хочу знать, сколько у меня чихуахуа, я печатаю count['animals']['dogs']['chihuahua']
Но я тоже хочу получить доступ count['vehicles']['cars']['vw golf']
, и вместо ключевых ошибок я хочу вернуть 0.
на самом деле я делаю это:
if not 'vehicles' in count:
count['vehicles'] = {}
if not 'cars' in count['vehicles']:
count['vehicles']['cars'] = {}
if not 'vw golf' in count['vehicles']['cars']['vw golf']:
count['vehicles']['cars']['vw golf'] = 0
Как я могу сделать это лучше?
Я думаю о каком-то типе класса, который наследуется от dict , но это всего лишь идея.
Комментарии:
1.
defaultdict
s.
Ответ №1:
Вы можете просто сделать:
return count.get('vehicles', {}).get('cars', {}).get('vw golf', 0)
в принципе, верните пустой словарь, если он не найден, и получите счетчик в конце.
Это будет работать при условии, что набор данных находится только в указанном формате. Это не приведет к возникновению ошибок, однако вам может потребоваться настроить его для других типов данных
ДЕМОНСТРАЦИЯ
>>> count = {'animals': {'dogs': {'chihuahua': 23}}}
>>> count.get('vehicles', {}).get('cars', {}).get('vw golf', 0)
0
>>> count = {'vehicles': {'cars': {'vw golf': 100}}}
>>> count.get('vehicles', {}).get('cars', {}).get('vw golf', 0)
100
>>>
Комментарии:
1. Просто потрясающе, никогда не думал, что это будет так просто.
2. Я никогда не сомневался 🙂
3. Итак, как бы вы добавили
bikes
vehicles
категорию в произвольной точке программы, не выполняя явную проверкуcount['vehicles']
, существует ли?4. Вопрос был о получении значений, и я явно упомянул, что это должно быть изменено для других случаев использования. @LukasGraf
Ответ №2:
Используйте комбинацию collections.defaultdict
и collections.Counter
:
from collections import Counter
from collections import defaultdict
counts = defaultdict(lambda: defaultdict(Counter))
Использование:
>>> counts['animals']['dogs']['chihuahua'] = 23
>>> counts['vehicles']['cars']['vw golf'] = 100
>>>
>>> counts['animals']['dogs']['chihuahua']
23
>>> # No fancy cars yet, Counter defaults to 0
... counts['vehicles']['cars']['porsche']
0
>>>
>>> # No bikes yet, empty counter
... counts['vehicles']['bikes']
Counter()
lambda
В построении defaultdict
необходимо, потому defaultdict
что ожидается фабрика. Таким lambda: defaultdict(Counter)
образом, в основном создается функция, которая будет возвращаться defaultdict(Counter)
при вызове — это то, что требуется для создания описанного вами многомерного словаря:
Словарь, значения которого по умолчанию соответствуют словарю, значения которого по умолчанию соответствуют экземпляру Counter
.
Преимущество этого решения в том, что вам не нужно отслеживать, какие категории вы уже определили. Вы можете просто назначить две новые категории и новое количество за один раз и использовать тот же синтаксис для добавления нового количества для существующих категорий:
>>> counts['food']['fruit']['bananas'] = 42
>>> counts['food']['fruit']['apples'] = 3
(Это предполагает, что вам всегда нужно ровно три измерения для вашей структуры данных, первые два из которых являются словарями категорий, а третье Counter
— где будет храниться фактическое количество вещей).