多层级可变深度的defaultdict?

89 投票
9 回答
47675 浏览
提问于 2025-04-16 14:04

我有一个很长的列表,像这样:

[A][B1][C1]=1
[A][B1][C2]=2
[A][B2]=3
[D][E][F][G]=4

我想要创建一个多层的字典,像这样:

A
--B1
-----C1=1
-----C2=1
--B2=3
D
--E
----F
------G=4

我知道如果我用递归的默认字典(defaultdict),我可以写 table[A][B1][C1]=1table[A][B2]=2,但是这样做只能在我提前写好这些插入语句的情况下才能工作。

在解析这个列表的时候,我不知道我需要多少个方括号([])来调用 table[key1][key2][...]

9 个回答

11

我会用一个叫做 dict 的子类来实现这个功能,并且在里面定义一个叫 __missing__ 的方法:

>>> class NestedDict(dict):
...     def __missing__(self, key):
...             self[key] = NestedDict()
...             return self[key]
...
>>> table = NestedDict()
>>> table['A']['B1']['C1'] = 1
>>> table
{'A': {'B1': {'C1': 1}}}

你不能直接用 defaultdict,因为 defaultdict 在初始化时需要一个工厂函数,但在初始化的时候,没办法描述同样的 defaultdict。上面的这个结构做的事情和 defaultdict 一样,但因为它是一个有名字的类(叫 NestedDict),所以在遇到缺失的键时,它可以自己引用自己。你也可以继承 defaultdict 并重写 __init__ 方法。

20

你的例子说明在任何层级上都可以有一个值,也可以有一个包含子元素的字典。这种结构叫做,而且有很多种实现方式。这里有一个例子:

from collections import defaultdict
class Tree(defaultdict):
    def __init__(self, value=None):
        super(Tree, self).__init__(Tree)
        self.value = value

root = Tree()
root.value = 1
root['a']['b'].value = 3
print root.value
print root['a']['b'].value
print root['c']['d']['f'].value

输出结果:

1
3
None

你也可以通过把输入写成JSON格式,然后使用json.load来读取它,这样就能把它当作一个嵌套字典的结构。

219

你甚至可以不定义一个类就做到这一点:

from collections import defaultdict

nested_dict = lambda: defaultdict(nested_dict)
nest = nested_dict()

nest[0][1][2][3][4][5] = 6

撰写回答