So I am trying to recursively flatten a python dictionary but I am having issues when the list of one of the values has a len greater than 1. The structure of the data is always, but in value can 1 or greater...
{'id': 123,
'in': [{'abs': 0.42, 'tpr': 0.99}, {'abs': 0.77, 'tpr': 0.98}],
'out': {'vbv': None, 'xyz': None},
'start': '20/06/2019'}
Here is the flatten I have already:
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 I run this through the flatten func I end up with:
{'id': 123,
'in_abs': 0.77,
'in_tpr': 0.98,
'out_vbv': None,
'out_xyz': None,
'start': '20/06/2019'}
So essentially I lose that first entry, I figured it might be an index issue so added a count to the out.update line, but its not that.
The desired output would be:
{'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'}
Working example:
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))
EDIT
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
This will output:
{'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'}