我有一组任意 JSON 数据,已在 Python 中解析为字典列表和不同深度的列表。我需要能够将其“扁平化”为一个字典列表。下面的例子:
源数据示例1
[{u'industry': [
{u'id': u'112', u'name': u'A'},
{u'id': u'132', u'name': u'B'},
{u'id': u'110', u'name': u'C'},
],
u'name': u'materials'},
{u'industry': {u'id': u'210', u'name': u'A'},
u'name': u'conglomerates'}
]
期望结果示例 1
[{u'name':u'materials', u'industry_id':u'112', u'industry_name':u'A'},
{u'name':u'materials', u'industry_id':u'132', u'industry_name':u'B'},
{u'name':u'materials', u'industry_id':u'110', u'industry_name':u'C'},
{u'name':u'conglomerates', u'industry_id':u'210', u'industry_name':u'A'},
]
对于这个简单的例子来说,这很容易,但我并不总是有这种精确的字典列表结构,还有一层额外的字典列表。在某些情况下,我可能需要遵循相同的方法进行额外的嵌套。因此,我认为我需要递归,但我似乎无法让它发挥作用。
提议的方法
1) 对于每个字典列表,在每个键前面添加一个提供父键名称的“路径”。在上面的示例中,“industry”是包含字典列表的键,因此列表中的每个子字典都添加了“industry”。
2) 将“父”项目添加到列表中的每个字典 - 在本例中,“名称”和“行业”是顶级字典列表中的项目,因此“名称”键/值被添加到每个字典中“工业”中的项目。
我可以想象在某些情况下,您在“父”项中有多个字典列表,甚至是字典的字典,并且将这些子树中的每一个应用到子字典列表中是行不通的。因此,我假设“父”项始终是简单的键/值对。
再举一个例子来说明需要处理的数据结构的潜在变化。
源数据示例2
[{u'industry': [
{u'id': u'112', u'name': u'A'},
{u'id': u'132', u'name': u'B'},
{u'id': u'110', u'name': u'C', u'company': [
{u'id':'500', u'symbol':'X'},
{u'id':'502', u'symbol':'Y'},
{u'id':'504', u'symbol':'Z'},
]
},
],
u'name': u'materials'},
{u'industry': {u'id': u'210', u'name': u'A'},
u'name': u'conglomerates'}
]
期望结果示例 2
[{u'name':u'materials', u'industry_id':u'112', u'industry_name':u'A'},
{u'name':u'materials', u'industry_id':u'132', u'industry_name':u'B'},
{u'name':u'materials', u'industry_id':u'110', u'industry_name':u'C',
u'company_id':'500', u'company_symbol':'X'},
{u'name':u'materials', u'industry_id':u'110', u'industry_name':u'C',
u'company_id':'502', u'company_symbol':'Y'},
{u'name':u'materials', u'industry_id':u'110', u'industry_name':u'C',
u'company_id':'504', u'company_symbol':'Z'},
{u'name':u'conglomerates', u'industry_id':u'210', u'industry_name':u'A'},
]
我已经查看了其他几个示例,但似乎找不到适用于这些示例的示例。
有什么建议或指示吗?我花了一些时间尝试构建一个递归函数来处理这个问题,但几个小时后没有运气......
因一次失败的尝试而更新
def _flatten(sub_tree, flattened=[], path="", parent_dict={}, child_dict={}):
if type(sub_tree) is list:
for i in sub_tree:
flattened.append(_flatten(i,
flattened=flattened,
path=path,
parent_dict=parent_dict,
child_dict=child_dict
)
)
return flattened
elif type(sub_tree) is dict:
lists = {}
new_parent_dict = {}
new_child_dict = {}
for key, value in sub_tree.items():
new_path = path + '_' + key
if type(value) is dict:
for key2, value2 in value.items():
new_path2 = new_path + '_' + key2
new_parent_dict[new_path2] = value2
elif type(value) is unicode:
new_parent_dict[key] = value
elif type(value) is list:
lists[new_path] = value
new_parent_dict.update(parent_dict)
for key, value in lists.items():
for i in value:
flattened.append(_flatten(i,
flattened=flattened,
path=key,
parent_dict=new_parent_dict,
)
)
return flattened
我得到的结果是“无”对象的 231x231 矩阵 - 显然我遇到了递归失控的麻烦。
我尝试了一些额外的“从头开始”尝试,但都以类似的失败模式失败。