使用anytree和graphviz在python中渲染树,而不合并公共节点

vdzxcuhz  于 2022-11-19  发布在  Python
关注(0)|答案(3)|浏览(120)

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

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

但是当我用to_picture方法把树渲染成图片时,图像是-

我不希望公共节点被合并,因为它会向我的树中添加不需要的路径。

ztigrdn8

ztigrdn81#

节点使用其id排列在graphviz中。在您的示例中,图形仅使用节点名称生成,然后graphviz创建您获得的循环边。
您真正想要的是每个节点的不同id和与之关联的label
以下是根据您的阵列执行此操作的方式

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";
}

下图

ztyzrc3y

ztyzrc3y2#

anytreeto_picture()函数使用graphviz生成文件。
here = similar question可以读取:
graphviz使用节点id作为标签。如果不同的节点需要有相同的标签,标签必须显式定义。

zdwk9cvp

zdwk9cvp3#

我正准备实施推荐的修复程序,但发现使用UniqueDotExporter可以完美地处理重复的id!

相关问题