Add item to vector in nested tree structure

Jumping to the right, the best way to do this:

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

I want to insert :hellointo the deepest :childrenvector. Above I do this with help assoc-in.

Is there a better way than that assoc-in?
Or , if , when assoc-inis the only way, how would you handle assoc-inthe 2nd argument [k & ks]?

It's also good to know if there is something there that also works for inserting :worldinto an arbitrary vector :children... like a 3rd child or 2nd child of a 1st child.

+4
source share
2 answers

vector 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]}]}]}]}]}

3- 1- ,

(vec (interleave (repeat :children) [0 1 2]))
;=> [:children 0 :children 1 :children 2]

, . . ..

(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]}]}]}]}]}
+5

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]}]}]}]}]}
+2

Source: https://habr.com/ru/post/1535994/


All Articles