使用python中的递归函数从JSON中获取嵌套字典



这是我的JSON数据。JSON数据由一些属性组成,但我只需要命令和子命令属性。

{
command: 'abc',
depth: 1,
help: '...',
subcommands:[
{
command: 'abc folder',
depth: 2,
help: '...',
subcommands:[
{
command: 'abc folder add',
depth: 3,
help: '...',
subcommands:[
{
command: 'abc folder add id',
depth: 4,
help: '...',
subcommands: []
},
{
command: 'abc folder add type',
depth: 4,
help: '...',
subcommands: []
},
{
command: 'abc folder add name',
depth: 4,
help: '...',
subcommands: []
}]
}],
{
command: 'abc folder list',
depth: 3,
help: '...',
subcommands: []
},
{
command: 'abc folder view',
depth: 3,
help: '...',
subcommands: [
{
command: 'abc folder view id',
depth: 4,
help: '...',
subcommands: []
},
{
command: 'abc folder view type',
depth: 4,
help: '...',
subcommands: []
},
{
command: 'abc folder view name',
depth: 4,
help: '...',
subcommands: []
}
}]
}]
}

我想从JSON数据中检索的嵌套字典如下:

{
'abc':
{
'folder':
{
'add':
{
'id': {},
'type': {},
'name': {}
},
'list': {},
'view':
{
'id': {},
'type': {},
'name': {}
}
}
}
}

我需要使用递归函数,这样它才能用于更深层次的属性。它只需要使用命令和子命令。若子命令的值为空,那个么在结果中,相关属性的值也应该为空。请发布您的建议,有效地制作一个嵌套的python词典。

我们将感谢您的所有回答。谢谢

一种优雅的相互递归形式-

def solution(t = {}):
def one(t, pre):
if not t:
return {}
if isinstance(t, dict):
return 
{ t['command'][len(pre):]: 
one
( t['subcommands']
, t['command'] + ' '
)
}
elif isinstance(t, list):
return many(t, pre)
else:
raise TypeError
def many(ts, pre):
if not ts:
return {}
else:
return { **one(ts[0], pre), **many(ts[1:], pre) }
return one(t, "")

正如@Ajax1234所指出的,您必须修复输入subcommands才能使用list-

d = 
{'command': 'abc', 'depth': 1, 'help': '...', 'subcommands': [{'command': 'abc folder', 'depth': 2, 'help': '...', 'subcommands': [{'command': 'abc folder add', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder add id', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add type', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add name', 'depth': 4, 'help': '...', 'subcommands': []}]}, {'command': 'abc folder list', 'depth': 3, 'help': '...', 'subcommands': []}, {'command': 'abc folder view', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder view id', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view type', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view name', 'depth': 4, 'help': '...', 'subcommands': {}}]}]}]}
print(json.dumps(solution(d), indent = 2))

输出-

{
"abc": {
"folder": {
"add": {
"id": {},
"type": {},
"name": {}
},
"list": {},
"view": {
"id": {},
"type": {},
"name": {}
}
}
}
}

如果不将subcommands键映射到它们实际表示的命令列表,就无法将结构转换为有效的Python字典。然后可以将str.replace与递归一起使用:

from functools import reduce
data = {'command': 'abc', 'depth': 1, 'help': '...', 'subcommands': [{'command': 'abc folder', 'depth': 2, 'help': '...', 'subcommands': [{'command': 'abc folder add', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder add id', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add type', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add name', 'depth': 4, 'help': '...', 'subcommands': []}]}, {'command': 'abc folder list', 'depth': 3, 'help': '...', 'subcommands': []}, {'command': 'abc folder view', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder view id', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view type', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view name', 'depth': 4, 'help': '...', 'subcommands': {}}]}]}]}
def get_d(d, p = None):
return {d['command'] if p is None else d['command'].replace(p, '')[1:]:
reduce(lambda x, y:{**x, **y}, [get_d(i, d['command']) for i in d['subcommands']], {})}

import json
print(json.dumps(get_d(data), indent=4))

输出:

{
"abc": {
"folder": {
"add": {
"id": {},
"type": {},
"name": {}
},
"list": {},
"view": {
"id": {},
"type": {},
"name": {}
}
}
}
}

最新更新