在Python中有没有一种优雅的方法来构建多层字典?

5
我想要构建一个类似的多级词典:

我的意思是:

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

我的问题是是否存在一种函数,可以通过以下方式构建上述字典:
D = function(['a', 'b'], ['A', 'B'], ['1', '2'], {})
4个回答

7

使用copy函数可以指定不同的叶节点,否则所有叶节点都将指向同一个字典。

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'], {})

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': {}}}}
编辑: 在我的解决方案中,最后一个参数 {} 将被复制到输出的每个叶子中,作为对同一字典的引用。如果这是一个问题(使用不可变对象,例如浮点数、整数或字符串来替换它是另一回事),可以使用 @matt 的 copy.copy 想法。

2

使用递归编写很容易

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")

0
字典推导式是一个很酷的方法,但只有在嵌套深度固定的情况下才适用:
{x:{y:{z:{} for z in ['1', '2']} for y in 'AB'} for x in 'ab'}

假设深度固定,这使得它比其他答案不太有用。 - Junuxx
这并不会使答案变差,因为我明确说明了它可以在什么情况下使用。 - dmg
这并不是技术上的错误,你提到了假设是好的,但在我看来,这仍然是不灵活且难以维护的。问题中的字典很可能只是一个最小的例子。如果深度固定为12级,你还会这样做吗?我认为这并不是“优雅”的,正如问题标题所要求的那样。 - Junuxx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接