2016-05-21 5 views
4

Я извлечение (root, parent1, parent2, child1) из иерархической базы данных в форме из list of tuples как:списка кортежей в словарь словарей

[('HCS', 'Assured Build', 'Implementation', 'Hardware Stack'), 
('HCS', 'Assured Build', 'Implementation', 'SA and SF'), 
('HCS', 'Assured Build', 'Testing and Validation', 'NFRU-SS'), 
('HCS', 'Assured Build', 'Testing and Validation', 'NRFU-UC'), 
('HCS', 'Assured Platform', 'Restoration', 'AS Build'), 
('HCS', 'Assured Platform', 'Restoration', 'Capacity Management'), 
('HCS', 'Assured Platform', 'Migration', 'Document Review')] 

Я хочу создать словарь словаря хотел легко перебирать и создать представление дерева:

{"HCS": 
     {"Assured Build": 
      {"Implementation":{"Hardware Stack", "Software"}, 
      {"Testing and Validation":{"NRFU-SS", "NRFU-UC"} 
     }, 
     {"Assured Platform": 
       {"Restoration":{"AS Build","Capacity Management"}, 
       {"Migration":{"Document Review"}}, 
     } 

} 

Каков наилучший способ справиться с этим? Я пробовал namedtuple и defaultdict с ошибкой.

+2

Где «Программное обеспечение» поступает? – timgeb

+0

Чем больше я смотрю на пример, тем меньше я понимаю логику этого. Не могли бы вы подробнее рассказать, как получить словарь из списка кортежей? – timgeb

+0

Ваш ожидаемый результат недействителен. Вы хотите, чтобы значение, связанное с '' Assured Build '', было списком? –

ответ

8

Вам нужен defaultdict из defaultdict из defaultdict в виде list (или set при необходимости):

import json 
from collections import defaultdict 

l = [('HCS', 'Assured Build', 'Implementation', 'Hardware Stack'), 
    ('HCS', 'Assured Build', 'Implementation', 'SA and SF'), 
    ('HCS', 'Assured Build', 'Testing and Validation', 'NFRU-SS'), 
    ('HCS', 'Assured Build', 'Testing and Validation', 'NRFU-UC'), 
    ('HCS', 'Assured Platform', 'Restoration', 'AS Build'), 
    ('HCS', 'Assured Platform', 'Restoration', 'Capacity Management'), 
    ('HCS', 'Assured Platform', 'Migration', 'Document Review')] 

d = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) 
for key1, key2, key3, value in l: 
    d[key1][key2][key3].append(value) 

print(json.dumps(d, indent=4)) 

json.dumps() здесь только для симпатичной печати. Он печатает:

{ 
    "HCS": { 
     "Assured Platform": { 
      "Restoration": [ 
       "AS Build", 
       "Capacity Management" 
      ], 
      "Migration": [ 
       "Document Review" 
      ] 
     }, 
     "Assured Build": { 
      "Implementation": [ 
       "Hardware Stack", 
       "SA and SF" 
      ], 
      "Testing and Validation": [ 
       "NFRU-SS", 
       "NRFU-UC" 
      ] 
     } 
    } 
} 

Мы также можем сделать вложенную шаг defauldict инициализации немного больше родовое и extract that into a reusable method:

def make_defaultdict(depth, data_structure): 
    d = defaultdict(data_structure) 
    for _ in range(depth): 
     d = defaultdict(lambda d=d: d) 
    return d 

Затем, вы можете заменить:

d = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) 

с:

d = make_defaultdict(2, list) 
+0

Спасибо тонну. Немного новый для питона и не знает лямбда. Кроме того, может ли быть рекурсивным, если размер кортежа становится динамическим? – MalTec

+0

@MalTec не могли бы вы дать мне пример того, как он может стать динамичным? Благодаря! Хотя я работаю над тем, чтобы сделать этот шаг defaultdict более родовым. – alecxe

+0

[('HCS', 'Assured Build', 'Implementation', 'Hardware Stack'), ('HCS', 'Assured Build', 'Assured Build' «Выполнение», «SA и SF»), («HCS», «Гарантированная сборка», «Тестирование и проверка», «NFRU-SS», «child1»), («HCS», «Assured Build», Testing and Validation ',' NFRU-SS ',' child2 ']) Извините за то, что вы задали слишком много ложных данных, но какой лучший способ перебирать d? Мне нужен только JSON, но мне нужно добавить немного информации. – MalTec

Смежные вопросы