有没有办法让defaultdict也成为defaultdict的默认值?(即无限级递归defaultdict?)
我希望能够做到:
x = defaultdict(...stuff...)
x[0][1][0]
{}
所以,我可以做x = defaultdict(defaultdict)但这只是第二层:
x[0]
{}
x[0][0]
KeyError: 0
有些食谱可以做到这一点。但是仅仅使用普通的defaultdict参数就可以做到吗?
注意,这是在询问如何做一个无限级递归defaultdict,所以它与Python不同:defaultdict of defaultdict?,这是如何做一个两级defaultdict。
我可能最终会使用串模式,但当我意识到我不知道如何做时,它让我感兴趣。
@nucklehead的响应可以扩展到处理JSON中的数组:
def nested_dict(existing=None, **kwargs):
if existing is None:
existing = defaultdict()
if isinstance(existing, list):
existing = [nested_dict(val) for val in existing]
if not isinstance(existing, dict):
return existing
existing = {key: nested_dict(val) for key, val in existing.items()}
return defaultdict(nested_dict, existing, **kwargs)
下面是一个函数,用于嵌套的任意深度的任意基defaultdict。
(cross post from Can't pickle defaultdict)
def wrap_defaultdict(instance, times=1):
"""Wrap an instance an arbitrary number of `times` to create nested defaultdict.
Parameters
----------
instance - list, dict, int, collections.Counter
times - the number of nested keys above `instance`; if `times=3` dd[one][two][three] = instance
Notes
-----
using `x.copy` allows pickling (loading to ipyparallel cluster or pkldump)
- thanks https://stackoverflow.com/questions/16439301/cant-pickle-defaultdict
"""
from collections import defaultdict
def _dd(x):
return defaultdict(x.copy)
dd = defaultdict(instance)
for i in range(times-1):
dd = _dd(dd)
return dd
下面是一个递归函数,用于将递归默认字典转换为普通字典
def defdict_to_dict(defdict, finaldict):
# pass in an empty dict for finaldict
for k, v in defdict.items():
if isinstance(v, defaultdict):
# new level created and that is the new value
finaldict[k] = defdict_to_dict(v, {})
else:
finaldict[k] = v
return finaldict
defdict_to_dict(my_rec_default_dict, {})