鉴于下面的JSON,为给定的“id”创建“name”的分层列表的最佳方法是什么?层次结构中可以有任意数量的部分。
例如,提供id“156”将返回“添加存储设备,引导配置,配置”
我一直在研究使用iteritems()
,但可以提供一些帮助。
{
"result": true,
"sections": [
{
"depth": 0,
"display_order": 1,
"id": 154,
"name": "Configuration",
"parent_id": null,
"suite_id": 5
},
{
"depth": 1,
"display_order": 2,
"id": 155,
"name": "Guided Configuration",
"parent_id": 154,
"suite_id": 5
},
{
"depth": 2,
"display_order": 3,
"id": 156,
"name": "Add Storage Devices",
"parent_id": 155,
"suite_id": 5
},
{
"depth": 0,
"display_order": 4,
"id": 160,
"name": "NEW",
"parent_id": null,
"suite_id": 5
},
{
"depth": 1,
"display_order": 5,
"id": 161,
"name": "NEWS",
"parent_id": 160,
"suite_id": 5
}
]
}
答案 0 :(得分:2)
这是一种方法:
def get_path(data, section_id):
path = []
while section_id is not None:
section = next(s for s in data["sections"] if s["id"] == section_id)
path.append(section["name"])
section_id = section["parent_id"]
return ", ".join(path)
...假设data
是json.loads(json_text)
或类似的结果,而section_id
是int
(这就是你为ids提供的内容)那个例子JSON)。
对于您的示例用法:
>>> get_path(data, 156)
u'Add Storage Devices, Guided Configuration, Configuration'
答案 1 :(得分:0)
最简单的方法可能是创建一个将ID映射到名称的字典。例如:
name_by_id = {}
data = json.loads(the_json_string)
for section in data['sections']:
name_by_id[section['id']] = section['name']
或使用dict comprehensions:
name_by_id = {section['id']: section['name'] for section in data['sections']}
然后你可以获得特定元素:
>>> name_by_id[156]
... 'Add Storage Devices'
或获取所有ID:
>>> name_by_id.keys()
... [160, 161, 154, 155, 156]
答案 2 :(得分:0)
我相信你想要的东西:
def get_name_for_id(id_num, sections):
cur_depth = -1
texts = []
for elem in sections:
if elem['depth'] < cur_depth:
del texts[:]
elif elem['depth'] == cur_depth:
texts.pop()
texts.append(elem['name'])
cur_depth = elem['depth']
if elem['id'] == id_num:
return ', '.join(reversed(texts))
根据您的数据返回:
In [11]: get_name_for_id(156, data['sections'])
Out[11]: 'Add Storage Devices, Guided Configuration, Configuration'
此外,它会考虑基于depth
的层次结构,因此如果您的数据中id
156引用depth = 0
,则结果为:
In [16]: get_name_for_id(156, data['sections'])
Out[16]: 'Add Storage Devices'
如果id 156的深度为1,则返回的值为:
In [22]: get_name_for_id(156, data['sections'])
Out[22]: 'Add Storage Devices, Configuration'
基本上它会考虑树木:
深度156 = 0深度156 = 1深度156 = 2
154 156 154 154
| | |
| / \ 155
155 155 156 |
156
它返回从156到树根的路径中名称的串联。
答案 3 :(得分:0)
这可能是你想要的:
>>> sections = data['sections']
>>> lookup = {section['id']: section for section in sections}
>>> lookup[None] = {}
>>> for section in sections:
parent = lookup[section['parent_id']]
if 'childs' not in parent:
parent['childs'] = []
parent['childs'].append(section)
>>> def printRecurse (section, indent = 0):
if 'childs' in section:
section['childs'].sort(lambda x: x['display_order'])
for child in section['childs']:
print('{}{}: {}'.format(' ' * indent, child['id'], child['name']))
printRecurse(child, indent + 1)
>>> printRecurse(lookup[None])
154: Configuration
155: Guided Configuration
156: Add Storage Devices
160: NEW
161: NEWS
答案 4 :(得分:0)
null
,将None
替换为输入词典中的true
。
True
}
使用给定输入测试代码: -
def filtering(d,id_n):
names = []
while id_n:
id_n,name=[(sec['parent_id'],sec['name']) for sec in d['sections'] if sec['id'] == id_n][0]
names.append(name)
return names
d = {
"result": True, #making 'true' with 'True'
"sections": [
{
"depth": 0,
"display_order": 1,
"id": 154,
"name": "Configuration",
"parent_id": None,
"suite_id": 5
},
{
"depth": 1,
"display_order": 2,
"id": 155,
"name": "Guided Configuration",
"parent_id": 154,
"suite_id": 5
},
{
"depth": 2,
"display_order": 3,
"id": 156,
"name": "Add Storage Devices",
"parent_id": 155,
"suite_id": 5
},
{
"depth": 0,
"display_order": 4,
"id": 160,
"name": "NEW",
"parent_id": None,
"suite_id": 5
},
{
"depth": 1,
"display_order": 5,
"id": 161,
"name": "NEWS",
"parent_id": 160,
"suite_id": 5
}
]