Reputation: 205
I would like to create a mermaid graph from nested map like this
{"a" {"b" {"c" nil
"d" nil}}
"e" {"c" nil
"d" {"h" {"i" nil
"j" nil}}}}
I think it should first convert nested map to this form. Then it should be easy.
[{:out-path "a" :out-name "a"
:in-path "a-b" :in-name "b"}
{:out-path "a-b" :out-name "b"
:in-path "a-b-c" :in-name "c"}
{:out-path "a-b" :out-name "b"
:in-path "a-b-d" :in-name "d"}
{:out-path "e" :out-name "e"
:in-path "e-f" :in-name "f"}
{:out-path "e" :out-name "e"
:in-path "e-c" :in-name "c"}
{:out-path "e" :out-name "e"
:in-path "e-d" :in-name "d"}
{:out-path "e-d" :out-name "d"
:in-path "e-d-h" :in-name "h"}
{:out-path "e-d-h" :out-name "h"
:in-path "e-d-h-i" :in-name "i"}
{:out-path "e-d-h" :out-name "h"
:in-path "e-d-h-j" :in-name "j"}]
EDIT:
This is what I have created. But I have absolutely no idea how to add path to result map.
(defn myfunc [m]
(loop [in m out []]
(let [[[k v] & ts] (seq in)]
(if (keyword? k)
(cond
(map? v)
(recur (concat v ts)
(reduce (fn [o k2]
(conj o {:out-name (name k)
:in-name (name k2)}))
out (keys v)))
(nil? v)
(recur (concat v ts) out))
out))))
Upvotes: 0
Views: 369
Reputation: 17849
as far as i can see by mermaid docs, to draw the graph it is enough to generate all the nodes in the form of "x-->y" pairs.
we could do that with some a simple recursive function (i believe there are not so many levels in a graph to worry about stack overflow):
(defn map->mermaid [items-map]
(if (seq items-map)
(mapcat (fn [[k v]] (concat
(map (partial str k "-->") (keys v))
(map->mermaid v)))
items-map)))
in repl:
user>
(map->mermaid {"a" {"b" {"c" nil
"d" nil}}
"e" {"c" nil
"d" {"h" {"i" nil
"j" nil}}}})
;; ("a-->b" "b-->c" "b-->d" "e-->c" "e-->d" "d-->h" "h-->i" "h-->j")
so now you just have to make a graph of it like this:
(defn create-graph [items-map]
(str "graph LR"
\newline
(clojure.string/join \newline (map->mermaid items-map))
\newline))
update
you could use the same strategy for the actual map transformation, just passing the current path to map->mermaid
:
(defn make-result-node [path name child-name]
{:out-path path
:out-name name
:in-path (str path "-" child-name)
:in-name child-name})
(defn map->mermaid
([items-map] (map->mermaid "" items-map))
([path items-map]
(if (seq items-map)
(mapcat (fn [[k v]]
(let [new-path (if (seq path) (str path "-" k) k)]
(concat (map (partial make-result-node new-path k)
(keys v))
(map->mermaid new-path v))))
items-map))))
in repl:
user>
(map->mermaid {"a" {"b" {"c" nil
"d" nil}}
"e" {"c" nil
"d" {"h" {"i" nil
"j" nil}}}})
;; ({:out-path "a", :out-name "a", :in-path "a-b", :in-name "b"}
;; {:out-path "a-b", :out-name "b", :in-path "a-b-c", :in-name "c"}
;; {:out-path "a-b", :out-name "b", :in-path "a-b-d", :in-name "d"}
;; {:out-path "e", :out-name "e", :in-path "e-c", :in-name "c"}
;; {:out-path "e", :out-name "e", :in-path "e-d", :in-name "d"}
;; {:out-path "e-d", :out-name "d", :in-path "e-d-h", :in-name "h"}
;; {:out-path "e-d-h", :out-name "h", :in-path "e-d-h-i", :in-name "i"}
;; {:out-path "e-d-h", :out-name "h", :in-path "e-d-h-j", :in-name "j"})
Upvotes: 1