Разобрать ответ json, чтобы получить родительский / дочерний словарь
У меня есть список jsons (это первоначально ответ от getRases API TestRail), который я пытаюсь проанализировать. Вот пример 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:1
а также "id": 6,
являются самыми верхними уровнями родительских узлов, так как "parent_id": null
для них.
Я хочу, чтобы все дочерние узлы попадали под верхнюю часть большинства родителей. В этом примере вот отношения, основанные на parent_id
1 -> [2,7] -> 16
6 -> 3
Основная цель состоит в том, чтобы определить, каковы все дочерние (и дочерние) узлы для родительского узла верхнего уровня. Я не заинтересован в знании отношений между родителями и детьми.
что я хочу проанализировать, это получить следующий вывод:
{
1: [2,7,16],
6: 3
}
Один из подходов состоит в том, чтобы использовать несколько вложенных циклов for для каждого узла верхнего родительского узла, если он представлен как parent_id
и идти с этим рекурсивно, но это не выглядит очень хорошим подходом.
Буду признателен за любые комментарии / предложения
1 ответ
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
запрашивается из dict, но нет. То, что возвращает метод, будет помещено в dict с этим значением. Так например roots_dict[16]
когда первый доступ будет установлен равным roots_dict[2]
который в свою очередь попросит roots_dict[1]
что просто 1
, Остальное довольно просто.