这是我的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": {}
}
}
}
}