我試圖更新由嵌套的地圖和序列組成的結構中的值,但update-in
將無法工作,因爲我想允許通配符。我的手動方法導致我很難看,很大,嵌套for
和into {}
調用。我最終創建了一個採用結構,類似選擇器的序列和更新函數的函數。Clojure:更新,但通配符和路徑跟蹤
(defn update-each-in
([o [head & tail :as path] f]
(update-each-in o path f []))
([o [head & tail :as path] f current-path]
(cond
(empty? path) (f o current-path)
(identical? * head)
(cond
(map? o)
(into {} (for [[k v] o]
[k (update-each-in v tail f (conj current-path k))]))
:else (for [[i v] (map-indexed vector o)]
(update-each-in v tail f (conj current-path i))))
:else (assoc o head
(update-each-in (get o head) tail f (conj current-path head))))))
這讓我簡化我的更新以下
(def sample {"TR" [{:geometry {:ID12 {:buffer 22}}}
{:geometry {:ID13 {:buffer 33}
:ID14 {:buffer 55}}}
{:geometry {:ID13 {:buffer 44}}}]
"BR" [{:geometry {:ID13 {:buffer 22}
:ID18 {:buffer 11}}}
{:geometry {:ID13 {:buffer 33}}}
{:geometry {:ID13 {:buffer 44}}}]})
(update-each-in sample [* * :geometry * :buffer]
(fn [buf path] (inc buf)))
顯然,這與深度嵌套結構堆棧溢出的問題;儘管我遠沒有達到這個目標,但擁有一個強大的解決方案會很好。任何人都可以提出更簡單/更快/更優雅的解決方案嗎?這可以用減速器/換能器完成嗎?
UPDATE這是一個要求,更新函數也獲得它正在更新的值的完整路徑。
你能提供樣本預期的輸出到你的問題嗎? – Symfrog 2014-10-10 12:55:23
@Symfrog你可以評估整個例子,它會給你預期的輸出。 – skrat 2014-10-10 16:34:33