2013-02-18 2 views
4

Я хотел бы построить словарь многоуровневую такие как:Есть ли элегантный способ создания многоуровневого словаря в python?

A = { 
    'a': { 
     'A': { 
      '1': {}, 
      '2': {}, 
     }, 
     'B': { 
      '1': {}, 
      '2': {}, 
     }, 
    }, 
    'b': { 
     'A': { 
      '1': {}, 
      '2': {}, 
     }, 
     'B': { 
      '1': {}, 
      '2': {}, 
     }, 
    }, 
} 

Мой вопрос заключается в том, что существует ли функция, что я могу построить над дикцией по:

D = function(['a', 'b'], ['A', 'B'], ['1', '2'], {}) 

ответ

5

Это использует функцию копирования, чтобы указать другой узел листа , В противном случае все листы указывают на тот же словарь.

from copy import copy 

def multidict(*args): 
    if len(args) == 1: 
     return copy(args[0]) 
    out = {} 
    for x in args[0]: 
     out[x] = multidict(*args[1:]) 
    return out 

print multidict(['a', 'b'], ['A', 'B'], ['1', '2'], {}) 
+1

+1 для 'copy'. – eumiro

0

ДИКТ понимание есть прохладный подход к этому, но только если вы глубина вложенности фиксирована:

{x:{y:{z:{} for z in ['1', '2']} for y in 'AB'} for x in 'ab'} 
+0

Предполагаемая фиксированная глубина делает это менее полезным, чем другие ответы. – Junuxx

+0

это не делает ответ плохим, потому что я явно указываю, когда он может быть использован. – dmg

+0

Это не технически неправильно, и хорошо, что вы упоминали это предположение, но ИМХО это все еще негибко и трудно поддерживать. Вероятно также, что словарь в вопросе является лишь минимальным примером. Вы бы это сделали, если глубина была зафиксирована на 12 уровнях? Я не думаю, что он «изящный», как задает вопрос. – Junuxx

5
def multi(*args): 
    if len(args) > 1: 
     return {arg:multi(*args[1:]) for arg in args[0]} 
    else: 
     return args[0] 

multi(['a', 'b'], ['A', 'B'], ['1', '2'], {}) 

возвращает

{'a': {'A': {'1': {}, '2': {}}, 'B': {'1': {}, '2': {}}}, 
'b': {'A': {'1': {}, '2': {}}, 'B': {'1': {}, '2': {}}}} 

EDIT: В моем решении, последний аргумент {} будет скопирован в каждый лист на выходе в качестве ссылки на тот же словарь. Если это проблема (заменяя ее неизменяемым объектом, например float, integer или string, это другая вещь), используйте идею @matt copy.copy.

2

Это легко писать, используя recusion

def multi_level_dict(*args): 
    x = dict() 
    if args: 
     for k in args[0]: 
      x[k] = multi_level_dict(*args[1:]) 
    return x 

ваше дело будет

multi_level_dict(["a", "b"], ["A", "B"], ["1", "2"]) 

или даже

multi_level_dict("ab", "AB", "12") 
Смежные вопросы