使用anytree和graphviz在python中渲染树,而不合并公共节点 [英] Rendering a tree in python using anytree and graphviz, without merging common nodes

查看:183
本文介绍了使用anytree和graphviz在python中渲染树,而不合并公共节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用python3的anytree包从列表["abc", "abd", "aec", "add", "adcf"]创建树.在此树中,每个列表元素的第一个字符-a是一个根,随后,其他字符被添加为其子元素.当我渲染树时,它看起来像:

I am creating a tree from a list ["abc", "abd", "aec", "add", "adcf"] using anytree package of python3. In this tree first character of each list element - a is a root, and subsequently, other characters are added as their children. When I render tree it looks like:

a
├── b
│   ├── c
│   └── d
├── e
│   └── c
└── d
    ├── d
    └── c
        └── f

但是当我使用to_picture方法将树渲染为图片时,图像为-

But when I render the tree to picture using to_picture method, the image is -

我不希望合并公共节点,因为它会将不必要的路径添加到我的树中.

I don't want the common nodes to be merged, as it is adding unwanted paths to my tree.

推荐答案

graphviz中的节点使用其ID进行排列.在您的情况下,仅使用节点名称生成图形,然后graphviz在获得图形时创建回路边.

The node are arranged in graphviz using their id. In your case the graph is generated with just node names and then graphviz created the loop edge as you get it.

对于每个节点,您真正想要的是不同的id,并且与此节点相关联的label. DotExporter类具有名为nodeattrfunc的属性,我们可以向其中传递函数或lambda并为节点生成属性

What you really want is different id for each node and a label associated with the same. The DotExporter class has a attribute named nodeattrfunc to which we can pass a function or a lambda and generate attributes for the nodes

以下是基于数组的处理方式

Below is how you would do it based on your array

import anytree
from anytree import Node, RenderTree

data = ["abc", "abd", "aec", "add", "adcf"]
from anytree.exporter import DotExporter

nodes = {}
first_node = None

for elem in data:
    parent_node = None
    parent_node_name = ""
    for i, val in enumerate(elem):
        if i not in nodes:
            nodes[i] = {}
        key = parent_node_name + val
        if key not in nodes[i]:
            print("Creating new node for ", key)
            nodes[i][key] = Node(key, parent=parent_node, display_name=val)

        if first_node is None:
            first_node = nodes[i][key]
        parent_node = nodes[i][key]
        parent_node_name = val

print(nodes)
DotExporter(nodes[0]["a"],
            nodeattrfunc=lambda node: 'label="{}"'.format(node.display_name)).to_dotfile("graph.txt")
DotExporter(nodes[0]["a"],
            nodeattrfunc=lambda node: 'label="{}"'.format(node.display_name)).to_picture("graph.png")

这将生成下面的点文件

digraph tree {
    "a" [label="a"];
    "ab" [label="b"];
    "bc" [label="c"];
    "bd" [label="d"];
    "ae" [label="e"];
    "ec" [label="c"];
    "ad" [label="d"];
    "dd" [label="d"];
    "dc" [label="c"];
    "cf" [label="f"];
    "a" -> "ab";
    "a" -> "ae";
    "a" -> "ad";
    "ab" -> "bc";
    "ab" -> "bd";
    "ae" -> "ec";
    "ad" -> "dd";
    "ad" -> "dc";
    "dc" -> "cf";
}

以及下图

这篇关于使用anytree和graphviz在python中渲染树,而不合并公共节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆