Clojure 找到所有的父母就像穿过一棵树
我想使用Clojure 找到所有的父母就像穿过一棵树,clojure,zipper,Clojure,Zipper,我想使用clojure.zip遍历此树并打印节点及其父节点。我找不到父母。例如,:e的父项是:b ;; ;; :a ;; / \ ;; :b :c ;; /\ \ ;; :d :e :f ;; (def example [:a [:b [:d] [:e]] [:c [:f]]]) (def z (zip/vector-zip example)) (def locs (take-while (complement zip/end?) (iterate zip/n
clojure.zip
遍历此树并打印节点及其父节点。我找不到父母。例如,:e
的父项是:b
;;
;; :a
;; / \
;; :b :c
;; /\ \
;; :d :e :f
;;
(def example [:a [:b [:d] [:e]] [:c [:f]]])
(def z (zip/vector-zip example))
(def locs (take-while (complement zip/end?) (iterate zip/next z)))
(defn parent-of [loc]
(when-let [parent-loc (-> loc zip/up zip/left)]
(zip/node parent-loc)))
(defn visit-all []
(doseq [loc locs]
(let [node (zip/node loc)]
(when (keyword? node)
(println node "has parent" (parent-of loc))))))
结果是:
:a has parent nil
:b has parent :a
:d has parent :b
:e has parent [:d]
:c has parent [:b [:d] [:e]]
:f has parent :c
我可以继续改进函数的父级-我的下一个想法是转到最左边的节点。将有一个算法,将返回正确的答案,从所有位置-然而,这样做似乎是相当多的工作,为一个共同的要求
我是否应该采取更好的方法
编辑
这个问题不是关于clojure.walk或Spector的。我正在寻找一个使用clojure.zip
并给出我在问题中定义的父项的答案,它只是loc
上方的关键字。因此,如果给的父项的loc
是:f
,我希望它返回:c
如果有人告诉我,作为一种评论,拉链已经不再被真正使用,并说clojure.walk
或Spector
是当前导航树的最佳实践方式,那么这将有所帮助 为什么要使用zip/left
?节点的父节点正是它上面的节点,而不是它上面和左边的节点。您只需删除这些内容。这是我自己的答案:
(defn parent-of [loc]
(when-let [parent-loc (-> loc zip/up zip/up first)]
(zip/node parent-loc)))
它在所有情况下都能提供正确的输出:
:a has parent nil
:b has parent :a
:d has parent :b
:e has parent :b
:c has parent :a
:f has parent :c
您能为您尝试实现的功能提供示例输入和输出吗?我知道从技术上讲,zip/up
为父级提供了可能的重复。但父对象始终只是封闭向量。我需要(我相信)这个封闭向量的第一个元素。这就是为什么在我的问题中我说:e
的父节点是:b
,即使从技术上讲:e
的父节点是[:b[:d][:e]]
。如果只需要节点的标签,而不需要节点的结构,那么首先调用(z/loc(z/up loc))
。