多层级可变深度的defaultdict?
我有一个很长的列表,像这样:
[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]=1
,table[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