在嵌套树结构中向向量添加元素

时间:2014-04-10 20:20:32

标签: clojure

向右跳,更好的方法:

(assoc-in 
    {:children [{:children [{:children [{:children [{:children []}]}]}]}]} 
    [:children 0 :children 0 :children 0 :children 0 :children 0] 
    :hello)

我想将:hello插入最深的:children向量中。上面我正在使用assoc-in

有没有比assoc-in更好的方法? 或者,如果{/ 1}}是唯一的方法, if ,您将如何处理assoc-in的第二个参数assoc-in

也很好知道是否有一些东西也适用于插入[k & ks]和任意:world的矢量......就像第三个孩子或第二个孩子一样第一个孩子。

2 个答案:

答案 0 :(得分:5)

assoc-in的向量参数不必是文字,因此您可以根据需要构建它。

(def nested-map  
  {:children [{:children [{:children [{:children [{:children []}]}]}]}]})

(assoc-in nested-map (vec (take 10 (cycle [:children 0]))) :hello)
;=> {:children [{:children [{:children [{:children [{:children [:hello]}]}]}]}]}

或者对于第1个孩子的第2个孩子的第3个孩子,构建像

这样的路径
(vec (interleave (repeat :children) [0 1 2]))
;=> [:children 0 :children 1 :children 2]

更一般地说,您可以使用zippers随意移动嵌套地图,例如下一个孩子。运动功能可以组成等。

(require '[clojure.zip :as zip])

(def z (zip/zipper map? :children #(assoc % :children (vec %2)) nested-map))

(-> (ffirst (filter (comp zip/end? second)  ; find last
                    (partition 2 1 (iterate zip/next z)))) 
    (zip/edit (constantly :hello)) ; change to :hello
    zip/root) ; bubble up changes

;=> {:children [{:children [{:children [{:children [{:children [:hello]}]}]}]}]}

答案 1 :(得分:2)

您也可以将clojure.walk用于此

(require '[clojure.walk :as w])

(def nested-map  
  {:children [{:children [{:children [{:children [{:children []}]}]}]}]})

(w/postwalk (fn [node] (if (and (vector? node) (empty? node))
                         (conj node :hello)
                         node))
            nested-map)
=> {:children [{:children [{:children [{:children [{:children [:hello]}]}]}]}]}