The following nested list can be regarded as a representation of a (tree) graph:
li = {"fig", {"date", {"kumquat"}, {"papaya", {"peach"}, {"apple"}}},
{"mango", {"orange", {"pear"}, {"avocado"}}},
{"banana"}}
In the above, a string is a node in the tree, and any lists that follow it are subtrees rooted at that node.
What are some of the ways by which this can be converted into a graph (or more concretely, a list of DirectedEdge
s)? I've come up with one way, listed below. But I wanted to learn about other interesting approaches - for instance, pattern replacements might be used?
This is what I came up with:
h[{str_String}] := Sequence[];
h[{str_String, ls__List}] := {DirectedEdge[str, #[[1]]], h@#} & /@ {ls};
edges = Flatten@h@li
(*
{"fig" \[DirectedEdge] "date", "date" \[DirectedEdge] "kumquat",
"date" \[DirectedEdge] "papaya", "papaya" \[DirectedEdge] "peach",
"papaya" \[DirectedEdge] "apple", "fig" \[DirectedEdge] "mango",
"mango" \[DirectedEdge] "orange", "orange" \[DirectedEdge] "pear",
"orange" \[DirectedEdge] "avocado", "fig" \[DirectedEdge] "banana"}
*)
TreePlot[Rule @@@ edges, Automatic, "fig", DirectedEdges -> True,
VertexLabeling -> True]
Answer
edges = Cases[li,
{node_String, subtrees__List} :> (
node \[DirectedEdge] #[[1]] & /@ {subtrees}),
{0, ∞}] // Flatten
Note the level specification within Cases
.
Graph[edges,
VertexLabels -> "Name",
ImagePadding -> 30,
GraphLayout -> {
"LayeredEmbedding",
"RootVertex" -> "fig"}]
Comments
Post a Comment