我有一个我正在尝试解析的 json 列表(最初是来自 TestRail API getcases 的响应)。这是一个示例 json:
[
{
"id": 1,
"parent_id": null,
},
{
"id": 2,
"parent_id": 1,
},
{
"id": 6,
"parent_id": null,
},
{
"id": 16,
"parent_id": 2,
},
{
"id": 7,
"parent_id": 1,
},
{
"id": 3,
"parent_id": 6
}
]
我想做的是找出哪些 ID 属于原始父 ID。
例如 id:1
和 "id": 6,
是自 "parent_id": null
以来最顶级的父节点。
我想让所有的子节点都在最顶层的父节点之下。
在此示例中,这是基于 parent_id
1 -> [2,7] -> 16
6 -> 3
主要目标是确定顶级父节点的所有子(和子)节点。我对了解子 parent /子子女关系不感兴趣。
我要解析的是得到如下输出:
{
1: [2,7,16],
6: 3
}
一种方法是使用几个嵌套的 for 循环,对于每个顶级父节点检查它是否呈现为 parent_id
并递归地使用它,但这看起来不太像好方法。
如有任何意见/建议,我们将不胜感激
最佳答案
import json
from collections import defaultdict
data = json.loads(
'[{"id": 1, "parent_id": null}, {"id": 2, "parent_id": 1}, {"id": 6, "parent_id": null}, {"id": 16, "parent_id": 2}, {"id": 7, "parent_id": 1}, {"id": 3, "parent_id": 6}]')
parents = {d['id']: d['parent_id'] for d in data}
class RootsDict(dict):
def __missing__(self, key):
parent = parents[key]
if parent is None:
return key
else:
return self[parent]
roots_dict = RootsDict()
descendants = defaultdict(list)
for d in data:
id_ = d['id']
if d['parent_id'] is not None:
descendants[roots_dict[id_]].append(id_)
print(descendants) # {1: [2, 16, 7], 6: [3]}
roots_dict
的设计使得 roots_dict[node]
将返回 node
或 node
的顶级父级> 本身,如果它已经是一个根。 __missing__
是一种特殊的方法,可以为字典覆盖。当从字典请求 key
但不存在时调用它。无论方法返回什么,都将以该值放入字典中。因此,例如 roots_dict[16]
首次访问时将设置为等于 roots_dict[2]
,这反过来会请求 roots_dict[1]
,也就是 1
。剩下的就很简单了。
关于python - 解析 json 响应以获取父/子字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50162964/