多级defaultdict可变深度?

我有一个大的列表,如:

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

我想build立一个多层次的字典,如:

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

我知道,如果我使用recursiondefaultdict我可以写table[A][B1][C1]=1table[A][B2]=2 ,但这只适用于硬编码插入语句。

在parsing列表的时候,我没有预先调用table[key1][key2][...]多less个[ table[key1][key2][...]

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

 from collections import defaultdict nested_dict = lambda: defaultdict(nested_dict) nest = nested_dict() nest[0][1][2][3][4][5] = 6 

你的例子说,在任何级别都可以有一个值,也是一个子元素的字典。 这被称为 ,并且有许多可用的实现。 这是一:

 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中编写input并使用json.load将其作为嵌套字典的结构进行读取来执行类似的操作。

我会做一个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。 上面的构造和默认的dict一样,但是由于它是一个命名类(NestedDict),所以它可以引用自己,因为遇到了缺less的键。 也可以inheritancedefaultdict并覆盖__init__

我认为recursion字典最简单的实现是这样的。 只有叶节点可以包含值。

 # Define recursive dictionary tree = lambda: defaultdict(tree) 

用法:

 # Create instance mydict = tree() tree['a'] = 1 tree['b']['a'] = 2 tree['c'] tree['d']['a']['b'] = 0 # Print import prettyprint prettyprint.pp(tree) 

输出:

 { "a": 1, "b": { "a": 1 }, "c": {}, "d": { "a": { "b": 0 } } } 

这相当于上面的,但是避免了lambda表示法。 也许更容易阅读?

 def dict_factory(): return defaultdict(dict_factory) your_dict = dict_factory() 

另外 – 从评论 – 如果你想从现有的字典更新,你可以简单地打电话

 your_dict[0][1][2].update({"some_key":"some_value"}) 

为了给字典添加值。

Dan O'Huiginn在2010年的期刊上发表了一个非常好的解决scheme:

http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html

 >>> class NestedDict(dict): ... def __getitem__(self, key): ... if key in self: return self.get(key) ... return self.setdefault(key, NestedDict()) >>> eggs = NestedDict() >>> eggs[1][2][3][4][5] {} >>> eggs {1: {2: {3: {4: {5: {}}}}}} 

稍微不同的可能性,允许经常字典初始化:

 from collections import defaultdict def superdict(arg=()): update = lambda obj, arg: obj.update(arg) or obj return update(defaultdict(superdict), arg) 

例:

 >>> d = {"a":1} >>> sd = superdict(d) >>> sd["b"]["c"] = 2 

添加到@Hugo
要有最大深度:

 l=lambda x:defaultdict(lambda:l(x-1)) if x>0 else defaultdict(dict) arr = l(2) 

table['A']=defaultdict()