我有以下向量,[-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0]Clojure的平坦序列插入樹
其表示樹[[1 2 [3] [2 [4] 3]]]
其中-1開始一個新的分支,0結束它。如何將原始矢量轉換爲可用的樹狀clojure結構(嵌套矢量,嵌套地圖)?我認爲clojure.zip/zipper
可能會這樣做,但我不確定如何構建這些函數參數。
我有以下向量,[-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0]Clojure的平坦序列插入樹
其表示樹[[1 2 [3] [2 [4] 3]]]
其中-1開始一個新的分支,0結束它。如何將原始矢量轉換爲可用的樹狀clojure結構(嵌套矢量,嵌套地圖)?我認爲clojure.zip/zipper
可能會這樣做,但我不確定如何構建這些函數參數。
拉鍊是一個很好的工具:
(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))
不知怎的,這感覺就像作弊:
[(read-string
(clojure.string/join " "
(replace {-1 "[" 0 "]"}
[-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0])))]
這不是太硬了一些遞歸:
(defn numbers->tree [xs]
(letfn [(step [xs]
(loop [ret [], remainder xs]
(if (empty? remainder)
[ret remainder]
(let [x (first remainder)]
(case x
0 [ret (next remainder)]
-1 (let [[ret' remainder'] (step (next remainder))]
(recur (conj ret ret'), remainder'))
(recur (conj ret x) (next remainder)))))))]
(first (step xs))))
的想法是有一個功能(step
),找到一個子樹,並返回th在樹上還有哪些數字需要處理。它通過迭代(通過loop
)進行大部分輸入,並在運行到-1
時啓動它自己的遞歸實例。唯一棘手的部分是確保使用從這些遞歸調用返回的remainder
,而不是繼續處理中間的列表。
順便說一句,看'replace':你的地圖/大小寫就是'(替換{-1「[」0「]」} xs)'。 – amalloy
這是一個很好的觀點,是的 - 謝謝。 – bsvingen