问题描述
我已将 defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
形式的嵌套 defaultdict 转换为嵌套 dict。如何转换回相同的格式和数据类型?
解决方法
您可以预先创建目标 defaultdict 结构并使用递归函数复制其中的数据:
from collections import defaultdict
def copyToDefaultdict(source,target):
for k,v in source.items():
if isinstance(v,dict) and isinstance(target[k],defaultdict):
copyToDefaultdict(v,target[k])
else:
target[k] = v
输出:
target = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
source = { "a": { 10: { 'x':2,'y':3},12:{ 'z':4,'w':5} },"b": { 20: { 'p':6,'q':7},22:{ 'r':8,'s':9} } }
copyToDefaultdict(source,target)
target
defaultdict(<function <lambda> at 0x7fd9135d01e0>,{'a': defaultdict(<function <lambda>.<locals>.<lambda> at 0x7fd914f9a510>,{10: defaultdict(<class 'int'>,{'x': 2,'y': 3}),12: defaultdict(<class 'int'>,{'z': 4,'w': 5})
}),'b': defaultdict(<function <lambda>.<locals>.<lambda> at 0x7fd914f9a598>,{20: defaultdict(<class 'int'>,{'p': 6,'q': 7}),22: defaultdict(<class 'int'>,{'r': 8,'s': 9})
})
})
,
您可以为此编写递归函数,但棘手的部分当然是每个级别的 lambda
必须不同。可能有更优雅的方法,但以下方法有效:
from collections import defaultdict
def deepdefaultdict(inner,depth):
return defaultdict(inner if depth == 1 else
lambda: deepdefaultdict(inner,depth - 1))
def convert(d,depth,inner):
if isinstance(d,dict):
res = deepdefaultdict(inner,depth)
res.update({x: convert(d[x],depth-1,inner) for x in d})
return res
else:
return d
示例:
import pprint
d = {1: {2: {3: 42}}}
d = convert(d,3,int)
d[2][3][4]
pprint.pprint(d)
输出:
defaultdict(<function deepdefaultdict.<locals>.<lambda> at 0xb75ec974>,{1: defaultdict(<function deepdefaultdict.<locals>.<lambda> at 0xb75be9bc>,{2: defaultdict(<class 'int'>,{3: 42})}),2: defaultdict(<function deepdefaultdict.<locals>.<lambda> at 0xb764b92c>,{3: defaultdict(<class 'int'>,{4: 0})})})