【问题标题】:Rendering a tree in python using anytree and graphviz, without merging common nodes使用anytree和graphviz在python中渲染树,而不合并公共节点
【发布时间】:2018-08-26 06:16:52
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你能分享你的代码吗?
  • 你想要这样的东西吗? i.stack.imgur.com/uRwYG.png
  • @Rojan.. 感谢您的关注。代码可以参考 Tarun Lalwani 的回答。

标签: python-3.x graphviz anytree


【解决方案1】:

节点使用它们的 id 排列在graphviz 中。在您的情况下,该图仅使用节点名称生成,然后 graphviz 在您得到它时创建了循环边。

您真正想要的是每个节点的id 和与之关联的label 不同。 DotExporter 类有一个名为 nodeattrfunc 的属性,我们可以向其传递函数或 lambda 并为节点生成属性

下面是你如何根据你的数组来做的

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

还有下图

【讨论】:

【解决方案2】:

作为anytreeto_picture()函数使用graphviz生成文件。

来自here = similar question,您可以阅读:

graphviz 使用节点 id 作为标签。如果不同的节点需要具有相同的标签,则必须明确定义标签。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 2020-01-03
    • 2018-12-29
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多