首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure Zipper to EDN

Clojure Zipper to EDN
EN

Stack Overflow用户
提问于 2015-02-20 19:16:28
回答 2查看 279关注 0票数 2

我使用Clojure Zipper创建了以下图表

代码语言:javascript
复制
   A
 / | \      
B  C  D
     / \
    E   F

使用以下代码:

代码语言:javascript
复制
(require '[clojure.zip :as z])    
(def g (z/vector-zip ["A" ["B" "C" "D"["E" "F"]]]))

现在我想在d3中创建一个可视化,这样我就可以用EDN格式来表示图形,比如

代码语言:javascript
复制
[{:from "A" :to "B"}
 {:from "A" :to "C"}
 {:from "A" :to "D"}
 {:from "D" :to "E"}
 {:from "D" :to "F"}]

我试过了

代码语言:javascript
复制
(loop [t g]
  (if-not (z/end? t)
    (do
      (if-not (z/branch? t)
        (println {:from (-> t (get 1) :ppath :l) :to (z/node t)})
        )
      (recur (z/next t))
      )
    )
  )

唯一的问题是子节点E& F,我无法跟踪它的父节点D。

EN

回答 2

Stack Overflow用户

发布于 2015-02-20 23:29:55

您可以稍微更改一下树的语法,基本上将一对父项和子项存储在一个向量中,然后滚动您自己的拉链。例如。

代码语言:javascript
复制
(def v [\a [\b [\c [\z]] [\d [\e \f]]]])
(def g 
  (z/zipper 
    vector? ; a vector/pair is a branch
    #(concat (second %)) ; might be a smarter way to get the childs
    nil ; don't support edit
    v))
(loop [t (z/next g)] ; skip first
  (if-not (z/end? t)
    (do
      (println {
                :from (-> t z/up z/node first) ; parents are always vectors
                :to (if (z/branch? t) (-> t z/node first) (z/node t))}) ; if vector, then first
      (recur (z/next t)))))

;;=> {:from a, :to b}
;;=> {:from a, :to c}
;;=> {:from c, :to z}
;;=> {:from a, :to d}
;;=> {:from d, :to e}
;;=> {:from d, :to f}
票数 1
EN

Stack Overflow用户

发布于 2015-02-23 00:11:36

我认为@cfrick的回答是有道理的。在树向量中包含成对的[父子节点]会更方便。尽管如此,这里有一个解决方案,您可以保留您的结构并使用vector-zip

parent-node获取当前拉链并返回定义结构中的父节点。例如,当zipper在节点:c上时,parent-node返回:a

edge-seq构建了一个惰性序列的图的边。它对于过滤特定的边缘非常有用。

代码语言:javascript
复制
(defn edges [vtree]
  (letfn [(parent-node [vz]
            (if-not (-> vz z/node vector?)
              (-> vz
                  z/up
                  z/left
                  (#(when % (z/node %))))))
          (edge-seq [vz]
            (if-not (z/end? vz)
              (if-let [p (parent-node vz)]
                (cons {:from p :to (z/node vz)}
                      (lazy-seq (edge-seq (-> vz z/next))))
                (edge-seq (-> vz z/next)))))]
    (let [vz (z/vector-zip vtree)]
      (edge-seq vz))))

使用以下向量/树:

代码语言:javascript
复制
user> (def v [:a [:b :c :d [:e [:h] :f] :g]])
#'user/v
user> (pprint (edges v))
({:from :a, :to :b}
 {:from :a, :to :c}
 {:from :a, :to :d}
 {:from :d, :to :e}
 {:from :e, :to :h}
 {:from :d, :to :f}
 {:from :a, :to :g})

仅保留来自:d的边

代码语言:javascript
复制
user> (pprint (filter #(= :d (:from %)) (edges v)))
({:from :d, :to :e} {:from :d, :to :f})
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28627687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档