clojuretreezipper

Clojure flat sequence into tree


I have the following vector, [-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0]

which represents the tree [[1 2 [3] [2 [4] 3]]]

where -1 begins a new branch and 0 ends it. How can I convert the original vector into a usable tree-like clojure structure (nested vector, nested map)? I think clojure.zip/zipper might do it but I'm not sure how to build those function args.


Solution

  • Zippers are a good tool for this: 

    (require '[clojure.zip :as zip])
    
    (def in [-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0])
    (def out [[1 2 [3] [2 [4] 3]]])
    
    (defn deepen [steps]
      (->> steps
           (reduce (fn [loc step]
                     (case step
                       -1 (-> loc
                              (zip/append-child [])
                              (zip/down)
                              (zip/rightmost))
                       0 (zip/up loc)
                       (zip/append-child loc step)))
             (zip/vector-zip []))
           (zip/root)))
    
    (assert (= (deepen in) out))