How to increase the values ​​on the map

I wrap my head around the Clojure state. I come from languages ​​where the state can be mutated. For example, in Python, I can create a dictionary, put string => integer strings in it, and then go through the dictionary and increase the values.

How do I do this in idiomatic Clojure?

+7
source share
4 answers

Just create a new map and use it:

(def m {:a 3 :b 4}) (apply merge (map (fn [[kv]] {k (inc v) }) m)) ; {:b 5, :a 4} 
+2
source
 (def my-map {:a 1 :b 2}) (zipmap (keys my-map) (map inc (vals my-map))) ;;=> {:b 3, :a 2} 

To update only one key value:

 (update-in my-map [:b] inc) ;;=> {:a 1, :b 3} 

Since Clojure 1.7, you can also use update :

 (update my-map :b inc) 
+7
source

To update multiple values, you can also take advantage of reducing taking an already filled battery and applying a function to this and each member of the next collection.

 => (reduce (fn [ak] (update-in ak inc)) {:a 1 :b 2 :c 3 :d 4} [[:a] [:c]]) {:a 2, :c 4, :b 2, :d 4} 

Keep in mind the keys you need to wrap in vectors, but you can still perform several updates in nested structures, such as the original update.

If you made this a generic function, you can automatically wrap the vector over the key by checking it with coll ?:

 (defn multi-update-in [mvf & args] (reduce (fn [acc p] (apply (partial update-in acc (if (coll? p) p (vector p)) f) args)) mv)) 

which allows you to receive single-level / key updates without the need to wrap keys in vectors

 => (multi-update-in {:a 1 :b 2 :c 3 :d 4} [:a :c] inc) {:a 2, :c 4, :b 2, :d 4} 

but you can still perform nested updates

 (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"}} 
+2
source

I played with the same idea, so I came up with:

 (defn remap "returns a function which takes a map as argument and applies f to each value in the map" [f] #(into {} (map (fn [[kv]] [k (fv)]) %))) ((remap inc) {:foo 1}) ;=> {:foo 2} 

or

 (def inc-vals (remap inc)) (inc-vals {:foo 1}) ;=> {:foo 2} 
0
source

All Articles