[英]Converting a nested list of dictionary in Python
I would like to convert a nested list of dictionary into a substructure.我想将字典的嵌套列表转换为子结构。 And finding a robust way to do so.
并找到一种强大的方法来做到这一点。 The structure:
结构:
nested_list = [
{
"id" : "fruit",
"name" : "apple"
},
{
"name": "fruit"
},
{
"id" : "fruit",
"name" : "grape"
},
{
"id" : "fruit",
"name" : "pineapple"
},
{
"name": "vehicle"
},
{
"id" : "vehicle",
"name": "car"
},
{
"id" : "car",
"name": "sedan"
},
]
Into:进入:
{
"vehicle": {
"car": {
"sedan" : {}
}
},
"fruit" : {
"apple": {},
"grape": {},
"pineapple": {}
}
}
Note that in this case it can go two level down.请注意,在这种情况下,它可以向下两级。 But It can go three deep down as well.
但它也可以深入三个。 For example one additional entry:
例如一个额外的条目:
{
"id" : "sedan",
"name": "mini sedan"
}
My approach so far is:到目前为止,我的方法是:
for category in nested_list:
if 'id' not in category:
d[category['name']] = {}
for category in nested_list:
if 'id' in category and category['id'] in d:
d[category['id']][category['name']] = {}
elif 'id' in category and category['id'] not in d:
for k, v in d.items():
if category['id'] in v:
d[k][category['id']] = {category['name']: {}}
# If there are not top level key then do nothing
else:
pass
It works in this case.它适用于这种情况。 The problem is it's not robust enough.
问题是它不够健壮。 I'm thinking recursion but unable to crack it.
我正在考虑递归但无法破解它。 Can someone help out?
有人可以帮忙吗? Thank you
谢谢
You can use collections.defaultdict
and dict.setdefault
:您可以使用
collections.defaultdict
和dict.setdefault
:
from collections import defaultdict
nested_list = [
{
"id": "fruit",
"name": "apple"
},
{
"name": "fruit"
},
{
"id": "fruit",
"name": "grape"
},
{
"id": "fruit",
"name": "pineapple"
},
{
"name": "vehicle"
},
{
"id": "vehicle",
"name": "car"
},
{
"id": "car",
"name": "sedan"
},
{
"id": "sedan",
"name": "mini sedan"
},
]
working_dict = defaultdict(dict)
result_dict = {}
for item in nested_list:
name = item['name']
if 'id' in item:
id_ = item['id']
working_dict[id_].setdefault(name, working_dict[name])
else:
result_dict[name] = working_dict[name]
print(working_dict)
print(result_dict)
output:输出:
defaultdict(<class 'dict'>, {'fruit': {'apple': {}, 'grape': {}, 'pineapple': {}}, 'apple': {}, 'grape': {}, 'pineapple': {}, 'vehicle': {'car': {'sedan': {'mini sedan': {}}}}, 'car': {'sedan': {'mini sedan': {}}}, 'sedan': {'mini sedan': {}}, 'mini sedan': {}})
{'fruit': {'apple': {}, 'grape': {}, 'pineapple': {}}, 'vehicle': {'car': {'sedan': {'mini sedan': {}}}}}
dict
is mutable.dict
是可变的。working_dict
is reference table for all "id"
s. working_dict
是所有"id"
的参考表。{}
for it.{}
。id
field, as root elements into result_dict
.id
字段的元素作为根元素注册到result_dict
。If you don't want to use collections.defaultdict
, you can only use dict.setdefault
.如果您不想使用
collections.defaultdict
,则只能使用dict.setdefault
。 But it is more verbose.但它更冗长。
working_dict = {}
result_dict = {}
for item in nested_list:
name = item['name']
if 'id' in item:
id_ = item['id']
working_dict.setdefault(id_, {}).setdefault(name, working_dict.setdefault(name, {}))
else:
result_dict[name] = working_dict.setdefault(name, {})
print(result_dict)
You can also do it manually with a recursive function.您也可以使用递归函数手动执行此操作。 The idea:
想法:
id
keyid
键的元素id
in keys:id
元素:
# Recursive search
def iterdictAdd(d, id, name):
# For all element in the dict
for k, v in d.items():
# If key match -> add
if k == id:
d[id] = {**d[id], **{name: {}}}
return True
else:
# Recursive call
if isinstance(v, dict):
if iterdictAdd(v, id, name):
return True
return False
out = {}
# Iterate all dict
for dict_ in nested_list:
# Ignore elements without "id"
if "id" in dict_:
# Search and add this key
if not iterdictAdd(out, dict_["id"], dict_["name"]):
out[dict_["id"]] = {dict_["name"]: {}}
print(out)
# {'fruit': {
# 'apple': {},
# 'grape': {},
# 'pineapple': {}
# },
# 'vehicle': {
# 'car': {
# 'sedan': {}
# }
# }
# }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.