Рекурсивный поиск по словарю python для создания graphviz

У меня есть словарь с таким корпусом:

[
    {
        "children": [
            {
                "children": [
                    {
                        "children": [
                            {
                                "label": "Something20",
                                "id": 11
                            },
                            {
                                "label": "Something19",
                                "id": 12
                            }
                        ],
                        "label": "Something18",
                        "id": 5
                    },
                    {
                        "children": [
                            {
                                "label": "Something15",
                                "id": 13
                            }
                        ],
                        "label": "Something14",
                        "id": 6
                    }
                ],
                "label": "Something2",
                "id": 2
            },
            {
                "children": [
                    {
                        "children": [
                            {
                                "label": "Something10",
                                "id": 14
                            }
                        ],
                        "label": "Something9",
                        "id": 7
                    },
                    {
                        "label": "Something8",
                        "id": 8
                    }
                ],
                "label": "Somethin7",
                "id": 3
            },
            {
                "children": [
                    {
                        "label": "Something5",
                        "id": 9
                    },
                    {
                        "label": "Something4",
                        "id": 10
                    }
                ],
                "label": "Something2",
                "id": 4
            }
        ],
        "label": "Something1",
        "id": 1
    }
]

Как я могу рекурсивно искать этот dict для генерации данных Graphviz следующим образом:

Something1->Something2
Something1->Something7

Так, например, список под названием edges = [] и добавить к нему некоторые данные в виде элементов (только метки):

[("Something1", "Something2"), ("Something1", "Something7")]

После создания данных я могу просто сгенерировать объект в Graphviz (Generate PNG Image), представляющий древовидную структуру предоставленного словаря.

0
0
108
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите сделать это рекурсивно, у вас может быть функция, которая генерирует ребро из узла, которое передается каждому из его дочерних элементов, а также вызывает себя для каждого из дочерних элементов. Затем все, что вам нужно сделать, это вызвать его для каждого узла в корневом списке (и вам нужно собрать все сгенерированные ребра в список). Это можно реализовать следующим образом (root хранит ваши данные):

def get_edges(node):
    if "children" not in node: # ensure the node has children
        return []
    label = node["label"]
    children = node["children"]
    result = [(label, c["label"]) for c in children] # create the edges
    for c in children:
        result.extend(get_edges(c)) # travers the tree recursively and collect all edges
    return result

edges = sum(map(get_edges, root), []) # create and combine all the edge lists

Запуск этого кода с предоставленными вами данными дает следующее:

[('Something1', 'Something2'), ('Something1', 'Somethin7'), 
 ('Something1', 'Something2'), ('Something2', 'Something18'), 
 ('Something2', 'Something14'), ('Something18', 'Something20'), 
 ('Something18', 'Something19'), ('Something14', 'Something15'), 
 ('Somethin7', 'Something9'), ('Somethin7', 'Something8'), 
 ('Something9', 'Something10'), ('Something2', 'Something5'), 
 ('Something2', 'Something4')]

К сожалению, он возвращает TypeError: строковые индексы должны быть целыми числами

needtobe 13.08.2018 09:29

Я думаю, это происходит потому, что не всегда узел содержит «дочерний» ключ.

needtobe 13.08.2018 09:42

Я добавил проверку, чтобы убедиться, что у узла есть дочерние элементы. Но это решает другую проблему, которую имел код (если у узла нет дочерних узлов, python выдаст вам KeyError: 'children', а не TypeError, который вы описали). Я бы предположил, что в ваших данных есть узел, у которого есть дочерний элемент, который является только строкой, а не словарем. Я протестировал код с предоставленными вами данными и добавил результаты к своему ответу.

Leon 13.08.2018 11:55

Большое спасибо! Выяснил похожую вещь: если не дети: return [].

needtobe 13.08.2018 14:49

Другие вопросы по теме