Заполнение вложенного словаря

У меня длинный список вложенных кортежей, которые я повторяю и добавляю определенным образом, так что пустой словарь:

dict = {} 

будут заполнены следующим образом:

 dict = {a: {b:1,5,9,2,3}, b: {c:7,4,5,6,2,4}, c: {b:3,13,2,4,2}... } 

Итерация проверит, существует ли вложенный словарь, и если да, то он добавит значение, иначе создаст вложенный словарь. Моя бедная попытка выглядит примерно так:

 longlist = [(1,(a,b)),(2,(b,c)), (3,(c,b)) ... ] dict = {} for each in longlist: if dict[each[1][0]][each[1][1]]: dict[each[1][0]][each[1][1]].append(each[0]) else: dict[each[1][0]] = {} dict[each[1][0]][each[1][1]] = each[0] 

Имейте в виду, что это упрощенная версия, поэтому у меня больше, чем значения a, b, c, 1,2,3 в моей реальной версии.

Проблема с моим подходом заключается в том, что итерация терпит неудачу, потому что словарь пуст для начала или что родительский элемент гнезда не существует в dict. Мне становится сложно. Мне не удалось найти много информации в Интернете о том, как решать вложенные словари, поэтому я подумал, что здесь должно быть хорошо спросить. Мне нужна помощь.

2 Solutions collect form web for “Заполнение вложенного словаря”

Вот решение, использующее collections.defaultdict

 import random import collections choices = ['a', 'b', 'c', 'd', 'e', 'f'] longlist = [] for i in range(1, 101): longlist.append((i, tuple(random.sample(choices, 2)))) print longlist final = collections.defaultdict(lambda: collections.defaultdict(list)) for value, (key1, key2) in longlist: final[key1][key2].append(value) print final 

В общем, способ, которым я бы изменил ваш код, состоял в том, чтобы сначала обеспечить наличие вложенных словарей (collection.defaultdict позаботится об этом для вас), а затем всегда добавлять один раз.

Что-то вроде

 for value (key1, key2) in longlist: if not your_dict.get(key1): your_dict[key1] = {} if not your_dict.get(key1).get(key2): your_dict[key1][key2] = [] your_dict[key1][key2].append(value) 

Также не для строки vs «для каждого …» Это распаковывает элементы в iterable. Вы также могли бы сделать

 for value, keys in longlist: 

но так как ключи являются итерабельными, вы также можете распаковать его, если вы завернете его в parens.

Не вникая в то, что вы пытаетесь сделать, вы можете переписать инструкцию if чтобы не выдавать ошибку, если ключи не существуют:

 if dict_.get(each[1][0], {}).get(each[1][1], None): dict_[each[1][0]][each[1][1]].append(each[0]) 

Функция dict.get – чрезвычайно полезная функция, поскольку она возвращает определенное значение по умолчанию, если данный ключ не существует.

Кроме того, похоже, вы ожидаете, что список будет существовать. В блоке else вы хотели это сделать?

 dict_[each[1][0]][each[1][1]] = [each[0]] 

Это создаст список с одним элементом, так что теперь dict[...][...].append(...) будет работать.

Я также не рекомендую использовать dict для обозначения вашей переменной. Он затеняет встроенный класс.

Дальнейшие улучшения могут включать распаковку элементов в заголовке цикла for, поэтому вам не нужно делать each[0] , each[1] и т. Д. Вы можете использовать что-то вроде:

 for idx, pair in longlist: x, y = pair # unpack each pair now ... 

Полный список:

 dict_ = {} for idx, pair in longlist: x, y = pair if dict_.get(x, {}).get(y, None): dict_[x][y].append(idx) else: dict_[x] = {y : [idx] } 

Это гораздо читательнее, чем раньше.

Interesting Posts

Изменение размера изображений в каталоге

Как выполнять транзакции базы данных с помощью psycopg2 / python db api?

python selenium очищает тём

Предупреждение при сохранении возможности в OpenERP

почему у моего colorbar есть строки?

В чем разница между eval, exec и компиляцией в Python?

Какова связь между временем процессора, измеряемым профилировщиком Python, и реальным, временем пользователя и sys?

odoo 9 – Поле не существует

Лучший способ проверить, пустой ли список

регулярное выражение python. Извлечение текста между шаблонами

Python – добавление списка в dict (начинающий)

Идиоматически преобразовывать объект BaseClass в объект SubClass?

Почему Python настолько медленный для простого цикла?

Как я могу сопоставить python, вызываемый над массивом numpy, как элегантным, так и эффективным способом?

Как я могу написать сервер сокета в другом потоке из моей основной программы (используя gevent)?

Python - лучший язык программирования в мире.