在Python中转换字典的嵌套列表
我想将嵌套字典列表转换为子结构。并找到一种强有力的方法来实现这一目标。结构:在Python中转换字典的嵌套列表,python,list,dictionary,Python,List,Dictionary,我想将嵌套字典列表转换为子结构。并找到一种强有力的方法来实现这一目标。结构: nested_list = [ { "id" : "fruit", "name" : "apple" }, { "name": "fruit" }, { "id" : "fruit", "name" : "grape" }, { "id" : "fruit", "name" : "pineapple" }, {
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"
}
到目前为止,我的做法是:
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
它在这种情况下起作用。问题是它不够健壮。我在考虑递归,但无法破解它。有人能帮忙吗?谢谢解决方案
您可以使用collections.defaultdict
和dict.setdefault
:
从集合导入defaultdict
嵌套列表=[
{
“id”:“水果”,
“名称”:“苹果”
},
{
“名称”:“水果”
},
{
“id”:“水果”,
“名称”:“葡萄”
},
{
“id”:“水果”,
“名称”:“菠萝”
},
{
“名称”:“车辆”
},
{
“id”:“车辆”,
“名称”:“汽车”
},
{
“id”:“汽车”,
“名称”:“轿车”
},
{
“id”:“轿车”,
“名称”:“迷你轿车”
},
]
工作目录=默认目录(目录)
结果_dict={}
对于嵌套列表中的项目:
名称=项目['name']
如果项目中有“id”:
id=项目['id']
工作指令[id].setdefault(名称,工作指令[name])
其他:
结果记录[名称]=工作记录[名称]
打印(工作指令)
打印(结果记录)
输出:
defaultdict(,{'fruit':{'apple':{},{'grape':{},{},{'spineapple':{},{'grape':{},{'spineapple':{},{'vehicle':{'sedan':{},{'mini sedan':{},{'sedan mini sedan':{},{'mini sedan
{'水果':{'苹果':{},'葡萄':{},'菠萝':{},'车辆':{'汽车':{'轿车':{'迷你轿车':{}}
解释
- 思想:
是可变的dict
是所有工作目录
的参考表id
- 如果没有这样的id,请为其注册
{}
- 并将没有
字段的元素作为根元素注册到id
中result\u dict
追加 如果不想使用
collections.defaultdict
,则只能使用dict.setdefault
。但它更冗长
working_dict={}
结果_dict={}
对于嵌套列表中的项目:
名称=项目['name']
如果项目中有“id”:
id=项目['id']
working_dict.setdefault(id_,{}).setdefault(name,working_dict.setdefault(name,{}))
其他:
result_dict[name]=working_dict.setdefault(name,{})
打印(结果记录)
您还可以使用递归函数手动执行此操作。这个想法:
- 迭代输入列表中的元素
- 忽略不带
键的元素id
- 对于键中具有
的元素:id
- 在输出中递归搜索此键
- 添加元素(如果元素已经存在,则在递归函数中添加元素,否则在之后添加)李>
嗨,当你说“嵌套列表”时,这是故意的吗?您提供的列表不是嵌套的。它包含同一级别的词典。哦,我错了。它不是嵌套列表。而是一个奇怪的层次结构你能分享一个有问题的输入的例子吗?有问题的输入?第一个列表是潜在的输入。我用了一个转换函数来返回输出,就像第二个字典一样,这很好。我认为使用defaultdict也是如此。但是我想要一个类似的答案:{'fruit':{'apple':{},'grape':{},'spineapple':{},'vehicle':{'car':{'sedan':{'mini sedan':{}}
result_dict
就是这样。哇,太神奇了。非常感谢你。我只是想知道有没有一种方法可以让常规代码这样做?如果没有,或者花太多时间,那很好,我不明白常规代码的意思。你能解释更多吗?那意味着不使用defaultdict
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
# 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': {}
# }
# }
# }