2016-07-12 48 views
0

我想创建嵌套地图mermaid图这样的Clojure - 变换嵌套地图

{"a" {"b" {"c" nil 
      "d" nil}} 
"e" {"c" nil 
     "d" {"h" {"i" nil 
       "j" nil}}}} 

diagram

我觉得应该先转换嵌套的地图这种形式。那么它应该很容易。

[{: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"}] 

编辑:

这是我创造。但我完全不知道如何添加结果地图的路径。

(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)))) 
+1

你需要用代码的具体帮助你试过了吗?你可以发布吗? – Bill

+0

@Bill,我需要帮助为每个项目添加“路径”。 – Ribelo

+0

通常,将当前级别的路径声明(让)到一个变量中,然后将其添加到正在构建的结构中,然后在递归到下一个级别并继续构建它时将其传递给它。在这种情况下,多元函数可能更容易构造,而不是循环。 – Bill

回答

1

据我可以通过人鱼文档看到,绘制图表它足以产生的“X - > Y”的形式的所有节点对。

,我们可以做到这一点与一些简单的递归函数(我相信,有没有在图表中这么多层次担心堆栈溢出):

(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))) 

在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") 

所以现在你只需要做一个这样的图表:

(defn create-graph [items-map] 
    (str "graph LR" 
     \newline 
     (clojure.string/join \newline (map->mermaid items-map)) 
     \newline)) 

更新

你可以使用同样的策略在实际地图变形,​​刚好路过电流路径map->mermaid

在REPL
(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)))) 

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"}) 
+0

我写了类似于你的东西。问题是密钥重复。你的结果图看起来像这样 https://i.imgur.com/padT6h7.png – Ribelo

+0

所以..那么得到一个“美人鱼”代码的例子,生成你想要的图表,我不是很熟悉与它.. – leetwinski

+0

或您的图片意味着两张不同的图表? – leetwinski