具有动态关键字名称Python的递归dict平坦器



所以我试图递归地压平python字典,但当其中一个值的列表的len大于1时,我遇到了问题。数据的结构总是,但in值可以是1或更大。。。

{'id': 123,
'in': [{'abs': 0.42, 'tpr': 0.99}, {'abs': 0.77, 'tpr': 0.98}],
'out': {'vbv': None, 'xyz': None},
'start': '20/06/2019'}

这是我已经做过的压平:

def flatten(d):
out = {}
for key, val in d.items():
if isinstance(val, dict):
val = [val]
if isinstance(val, list):
for subdict in val:
deeper = flatten(subdict).items()
out.update({key + '_' + key2: val2 for key2, val2 in deeper})
else:
out[key] = val
return out

如果我通过压平函数运行这个函数,我会得到:

{'id': 123,
'in_abs': 0.77,
'in_tpr': 0.98,
'out_vbv': None,
'out_xyz': None,
'start': '20/06/2019'}

所以基本上我丢失了第一个条目,我认为这可能是一个索引问题,所以在out.update行中添加了一个count,但事实并非如此。

所需输出为:

{'id': 123,
'in_0_abs': 0.42,
'in_0_tpr': 0.99,
'in_1_abs': 0.77,
'in_1_tpr': 0.98,
'out_vbv': None,
'out_xyz': None,
'start': '20/06/2019'}

工作示例:

import pprint as pp

def flatten(d):
out = {}
for key, val in d.items():
if isinstance(val, dict):
val = [val]
if isinstance(val, list):
for subdict in val:
deeper = flatten(subdict).items()
out.update({key + '_' + key2: val2 for key2, val2 in deeper})
else:
out[key] = val
return out

if __name__ == '__main__':
INPUT = {'id': 123, 'in': [{'abs': 0.42, 'tpr': 0.99}, {'abs': 0.77, 'tpr': 0.98}],
'out': {'vbv': None, 'xyz': None},
'start': '20/06/2019'}
pp.pprint(flatten(INPUT))

编辑

def flatten(d):
out = {}
for key, val in d.items():
if isinstance(val, dict):
val = [val]
if isinstance(val, list):
for index, subdict in enumerate(val):
deeper = flatten(subdict).items()
out.update({key + '_' + key2 + '_' + str(index): val2 for key2, val2 in deeper})
else:
out[key] = val
return out

这将输出:

{'id': 123,
'in_abs_0': 0.42,
'in_abs_1': 0.77,
'in_tpr_0': 0.99,
'in_tpr_1': 0.98,
'out_vbv_0': None,
'out_xyz_0': None,
'start': '20/06/2019'}

遇到列表时,需要一个索引/计数变量。

def flatten(d):
out = {}
# pdb.set_trace()
for key, val in d.items():
if isinstance(val, dict):
val = [val]
if isinstance(val, list):
count = 0
for subdict in val:
deeper = flatten(subdict).items()
if (len(val) > 1):
out.update({key + '_' + str(count) + '_' + key2: val2 for key2, val2 in deeper})
count = count + 1
else:
out.update({key + '_' + key2: val2 for key2, val2 in deeper})
else:
out[key] = val
return out

输出

{'id': 123,
'in_0_abs': 0.42,
'in_0_tpr': 0.99,
'in_1_abs': 0.77,
'in_1_tpr': 0.98,
'out_vbv': None,
'out_xyz': None,
'start': '20/06/2019'}

使用enumerate:

def flatten(d):
out = {}
for key, val in d.items():
if isinstance(val, dict):
val = [val]
if isinstance(val, list):
for index, subdict in enumerate(val):
deeper = flatten(subdict).items()
out.update({key + '_' + key2 + '_' + str(index): val2 for key2, val2 in deeper})
else:
out[key] = val
return out

最新更新