'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created.
(def users [{:name "James" :age 26} {:name "John" :age 43}]) ;;=> #'user/users ;; similar to assoc-in but does not simply replace the item. ;; the specified function is performed on the matching item. ;; here the age of the second (index 1) user is incremented. (update-in users [1 :age] inc) ;;=> [{:name "James", :age 26} {:name "John", :age 44}]
(def p {:name "James" :age 26}) ;;=> #'user/p (update-in p [:age] inc) ;;=> {:name "James", :age 27} ;; remember, the value of p hasn't changed! (update-in p [:age] + 10) ;;=> {:name "James", :age 36} ;; Here we see that the keyed object is ;; the first argument in the function call. ;; i.e. :age (- 26 10) => 16 (update-in p [:age] - 10) ;;=> {:name "James", :age 16}
(defn char-cnt [s] "Counts occurence of each character in s" (reduce (fn [m k] (update-in m [k] (fnil inc 0))) {} s)) ;; Note use of fnil above ;; - returns 0 if nil is passed to inc (avoids null pointer exception) (char-cnt "foo-bar") ;;=> {\r 1, \a 1, \b 1, \- 1, \o 2, \f 1}
;; f has args ;; The keyed value is placed as the first argument ;; :a (/ 3 4 5) => 3/20 (update-in {:a 3} [:a] / 4 5) ;;=> {:a 3/20}
;; be careful with that empty path sequence, it's seldom what you want (update-in {} [] (constantly {:k :v})) ;;=> {nil {:k :v}} ;; In general, you find that for a non-empty path ;; (get-in (update-in m path (constantly v)) path) ;; is equal to v. ;; Surprisingly this does not hold true in case of an empty path.
;;You can use update-in in a nested map too, in order to update more than ;;one value: (def m {:1 {:value 0, :active false}, :2 {:value 0, :active false}}) (update-in m [:1] assoc :value 1 :active true) ;;=>{:1 {:value 1, :active true}, :2 {:value 0, :active false}}
;; We may dig into multiple levels with `update-in`: (def player1 {:name "Player 1" :attribs {:str 10 :int 11 :wis 9}}) (update-in player1 [:attribs :str] inc) ;; {:name "Player 1", :attribs {:str 11, :int 11, :wis 9}} (update-in player1 [:attribs :str] * 2) ;; {:name "Player 1", :attribs {:str 20, :int 11, :wis 9}} ;; We can see one level via `update`... (update player1 :attribs #(update % :str inc)) ;; {:name "Player 1", :attribs {:str 11, :int 11, :wis 9}}
;; can mix associative types as well user=> (update-in [1 {:a 2 :b 3 :c 4}] [1 :c] (fnil inc 5)) ;; => [1 {:a 2, :b 3, :c 5}] user=> (update-in [1 {:a 2 :b 3 :c 4}] [1 :d] (fnil inc 5)) ;; => [1 {:a 2, :b 3, :c 4, :d 6}] ;; but of course vector indices must be appropriate types user=> (update-in [1 {:a 2 :b 3 :c 4}] [:b :c] (fnil inc 5)) IllegalArgumentException Key must be integer clojure.lang.APersistentVector.assoc (APersistentVector.java:345)
(def ds [{:id 1.0 :name "name1"} {:id 2.0 :name "name2"} {:id 3.0 :name "name3"}]) (map (fn [x] (update-in x [:name] #(if (= "name2" %) % "not 2"))) ds) ;; | :id | :name | ;; |-----+-------| ;; | 1.0 | not 2 | ;; | 2.0 | name2 | ;; | 3.0 | not 2 |
Associates a value in a nested associative structure, where ks is a sequence of keys and v is the ...
Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil i...
Takes a function f, and returns a function that calls f, replacing a nil first argument to f with ...
'Updates' a value in an associative structure, where k is a key and f is a function that will take...
update-in