so I got the following problem.
I am building a tree that shows dependencies with the Python Module 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(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.
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. So you can not have your C
node have both B
and E
as parent. There is no solution for that other than using another library, which can support (directed) graphs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.