我在Clojure中圍繞着我的狀態。我來自可以突變狀態的語言。例如,在Python中,我可以創建一個字典,在其中放入一些字符串=>整數對,然後遍歷字典並遞增值。如何在地圖中增加值
我該如何在習慣Clojure中做到這一點?
我在Clojure中圍繞着我的狀態。我來自可以突變狀態的語言。例如,在Python中,我可以創建一個字典,在其中放入一些字符串=>整數對,然後遍歷字典並遞增值。如何在地圖中增加值
我該如何在習慣Clojure中做到這一點?
只是produce新地圖,並使用它:
(def m {:a 3 :b 4})
(apply merge
(map (fn [[k v]] {k (inc v) }) m))
; {:b 5, :a 4}
(def my-map {:a 1 :b 2})
(zipmap (keys my-map) (map inc (vals my-map)))
;;=> {:b 3, :a 2}
要通過密鑰更新只有一個值:
(update-in my-map [:b] inc) ;;=> {:a 1, :b 3}
由於Clojure的1.7它也可以使用update
:
(update my-map :b inc)
要更新多個值,您還可以利用減少採取已填充的累加器,並在該集合和下列集合的每個成員上應用函數。
=> (reduce (fn [a k] (update-in a k inc)) {:a 1 :b 2 :c 3 :d 4} [[:a] [:c]])
{:a 2, :c 4, :b 2, :d 4}
注意的關鍵需要被封閉在載體的,但你仍然可以做多更新插件像在原來的更新嵌套結構。
如果你做了它廣義函數,你可以通過與COLL ?:
(defn multi-update-in
[m v f & args]
(reduce
(fn [acc p] (apply
(partial update-in acc (if (coll? p) p (vector p)) f)
args)) m v))
這將允許單級/密鑰更新,而不需要在載體包裹按鍵測試它自動包裹在一個關鍵的載體
=> (multi-update-in {:a 1 :b 2 :c 3 :d 4} [:a :c] inc)
{:a 2, :c 4, :b 2, :d 4}
,但仍然能夠做到嵌套更新
(def people
{"keith" {:age 27 :hobby "needlefelting"}
"penelope" {:age 39 :hobby "thaiboxing"}
"brian" {:age 12 :hobby "rocket science"}})
=> (multi-update-in people [["keith" :age] ["brian" :age]] inc)
{"keith" {:age 28, :hobby "needlefelting"},
"penelope" {:age 39, :hobby "thaiboxing"},
"brian" {:age 13, :hobby "rocket science"}}
我一直在玩弄同樣的想法,所以我想出了:
(defn remap
"returns a function which takes a map as argument
and applies f to each value in the map"
[f]
#(into {} (map (fn [[k v]] [k (f v)]) %)))
((remap inc) {:foo 1})
;=> {:foo 2}
或
(def inc-vals (remap inc))
(inc-vals {:foo 1})
;=> {:foo 2}
一個價值怎麼樣?那麼,如果我想要{a:7:b 4}。如果我有一個整數地圖的地圖,並想增加說key1 => subkey1 => integer ++的值? –
@DavidWilliams(update-in my-map [:b] inc);; => {:a 1,:b 3} –
明白了,這會創建一個新地圖,對嗎?我在想這會讓狀態更加艱難。例如,要創建貝葉斯分類器,我需要不斷地將事物的記錄更新爲多級結構。 key1 => subkey1 =>整數。我需要做som dosync和交換魔法嗎? –