data-structuresclojurezipper

How to move an element within a structure, possibly with zippers?


I have this structure:

 [{"a" {"b" 1 "c" 2} 
   "children" [{"a" {"b" 3 "c" 4} "children" []}]}
  {"a" {"b" 5 "c" 6} "children" []}
  {"a" {"b" 7 "c" 8}
    "children" [{"a" {"b" 9 "c" 10} "children" []} {"a" {"b" 10 "c" 10} "children" []}]}]

I'm trying to write an algorithm to move and element within a vector. For example in the last element, it has children vector with:

"children" [{"a" {"b" 9 "c" 10} "children" []} {"a" {"b" 10 "c" 10} "children" []}]

My function is supposed to search for a specific nested map - let's say, find the map where it is the value 10 for its b property. I will locate {"a" {"b" 10 "c" 10} "children" []}. Once I found it, I need to change its location with the vector. Let's assume, that children will become:

 "children" [{"a" {"b" 10 "c" 10} "children" []} {"a" {"b" 9 "c" 10} "children" []}]

With Zipper, I was able to traverse and locate the nested map but not sure how to move it within the vector.

Here is how my zipper is created:

  (z/zipper #(contains? % "children") #(get % "children")  (fn [_ c] c) data-structure)

Solution

  • This will do what I want:

    (defn update-tree [editable? edit loc]
      (loop [loc loc]
        (if (z/end? loc)
        (z/root loc)
        (if (editable? (z/node loc))
          (recur (-> loc z/up (z/edit edit) z/up z/next))
          (recur (z/next loc))))))
    

    But it is only working for this exact structure. Nesting more elements is breaking the algorithm.