简体   繁体   English

Anytree 模块/UniqueDotExporter 生成具有冗余边的树

[英]Anytree Module/UniqueDotExporter produces a Tree with redundant edges

so I got the following problem.所以我遇到了以下问题。

I am building a tree that shows dependencies with the Python Module anytree.我正在构建一棵树,显示与 Python 模块 anytree 的依赖关系。

Nodes are created with:节点是通过以下方式创建的:

Node(""+str(name), parent= parentname)

at the end of my program I want to create a graph with DotExporter.在我的程序结束时,我想用 DotExporter 创建一个图表。

DotExporter(root, nodeattrfunc=lambda n: 'label="%s"' % (n.name), edgeattrfunc=lambda parent, child: "style=bold").to_picture("filename.png)

The creation of the graph works, but now I got the problem that there are too many redundant edges in big trees.图的创建工作,但现在我遇到了大树中有太多冗余边的问题。

For example:例如:

A -> B -> C -> D
A -> E -> C -> D

The end graph will be right, but there will be 2 edges/arrows from C to D, but I only want it to show 1.结束图是正确的,但是从 C 到 D 会有 2 条边/箭头,但我只希望它显示 1。

How do I change that?我该如何改变呢?

Firstly, here is a Minimal Reproducible Example :首先,这是一个最小的可重现示例

from anytree import Node, render

a = Node(name="A", parent=None)
b = Node(name="B", parent=a)
c = Node(name="C", parent=b)
d = Node(name="D", parent=c)
e = Node(name="E", parent=a)
c2 = Node(name="C", parent=e)
d2 = Node(name="D", parent=c)
root = a
print(render.RenderTree(root).by_attr())
A
├── B
│   └── C
│       ├── D
│       └── D
└── E
    └── C

Regarding your question, you will have to remember which Nodes are already created, like so:关于您的问题,您必须记住已经创建了哪些节点,如下所示:

from anytree import Node, render


already_seen = {}


def create_node(name, parentname):
    if name in already_seen:
        if already_seen[name].parent.name == parentname:
            # edge already created
            child = already_seen[name]
            return child
        else:
            # the node already exists, but has a new parent
            parent = already_seen[parentname]
            child = already_seen[name]
            parent.children = parent.children + (child,)  # add to parent's children
            return child
    else:  # name never seen
        if parentname in already_seen:
            # new child for a known parent
            parent = already_seen[parentname]
            child = Node(name, parent=parent)
            already_seen[name] = child
            return child
        elif parentname is None:
            # a root
            root = Node(name, None)
            already_seen[name] = root
            return root
        else:
            raise ValueError("unknown parent name " + repr(parentname))


a = create_node(name="A", parentname=None)
b = create_node(name="B", parentname="A")
c = create_node(name="C", parentname="B")
d = create_node(name="D", parentname="C")
e = create_node(name="E", parentname="A")
c2 = create_node(name="C", parentname="E")
d2 = create_node(name="D", parentname="C")

root = a
print(render.RenderTree(root).by_attr())
A
├── B
└── E
    └── C
        └── D

But you have another problem: your graph dependency is not a tree : it is a (directed) graph !但是您还有另一个问题:您的图依赖关系不是:它是(有向)
But the library you are using, anytree , as the name implies, can only model trees.但是您使用的库anytree ,顾名思义,只能 model 树。 So you can not have your C node have both B and E as parent.所以你不能让你的C节点同时有BE作为父节点。 There is no solution for that other than using another library, which can support (directed) graphs.除了使用另一个可以支持(有向)图的库之外,没有其他解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM