Drewes
Drewes

Reputation: 2697

Update hierarchical / tree structure in Clojure

I have an Atom, like x:

(def x (atom {:name "A" 
              :id 1 
              :children [{:name "B"
                          :id 2 
                          :children []} 
                         {:name "C"
                          :id 3 
                          :children [{:name "D" :id 4 :children []}]}]}))

and need to update a submap like for example:

if :id is 2 , change :name to "Z"

resulting in an updated Atom:

{:name "A" 
 :id 1 
 :children [{:name "Z"
             :id 2
             :children []} 
            {:name "C"
             :id 3 
             :children [{:name "D" :id 4 :children []}]}]}

how can this be done?

Upvotes: 2

Views: 557

Answers (2)

rene_gr
rene_gr

Reputation: 489

You could also use Zippers from the clojure.zip namespace

Find a working example here: https://gist.github.com/renegr/9493967

Upvotes: 1

juan.facorro
juan.facorro

Reputation: 9930

You could do it with postwalk or prewalk from the clojure.walk namespace.

(def x (atom {:name "A" 
              :id 1 
              :children [{:name "B"
                          :id 2 
                          :children []} 
                         {:name "C"
                          :id 3 
                          :children [{:name "D" :id 4 :children []}]}]}))
(defn update-name [x]
  (if (and (map? x) (= (:id x) 2))
    (assoc x :name "Z")
    x))

(swap! x (partial clojure.walk/postwalk update-name))

Upvotes: 1

Related Questions