【问题标题】:Anytree Module/UniqueDotExporter produces a Tree with redundant edgesAnytree 模块/UniqueDotExporter 生成具有冗余边的树
【发布时间】:2022-01-17 22:25:15
【问题描述】:

所以我遇到了以下问题。

我正在构建一棵树,显示与 Python 模块 anytree 的依赖关系。

节点是通过以下方式创建的:

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

在我的程序结束时,我想用 DotExporter 创建一个图表。

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

图的创建工作,但现在我遇到了大树中冗余边太多的问题。

例如:

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

结束图是正确的,但是从 C 到 D 会有 2 条边/箭头,但我只希望它显示 1。

我该如何改变?

【问题讨论】:

    标签: python nodes dot edges anytree


    【解决方案1】:

    首先,这是一个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
    

    关于您的问题,您必须记住已经创建了哪些节点,如下所示:

    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
    

    但是您还有另一个问题:您的图形依赖不是tree:它是(定向的)graph
    但是您使用的库anytree,顾名思义,只能对树进行建模。所以你不能让你的C 节点同时拥有BE 作为父节点。除了使用另一个可以支持(有向)图的库之外,没有其他解决方案。

    【讨论】:

      猜你喜欢
      • 2021-04-05
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      相关资源
      最近更新 更多