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