assoc-in

added
1.0

ns
clojure.core

type
function

(assoc-in m [k & ks] v)

Associates a value in a nested associative structure, where ks is a
sequence of keys and v is 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}])

;; update the age of the second (index 1) user 
(assoc-in users [1 :age] 44)
;;=> [{:name "James", :age 26} {:name "John", :age 44}]

;; insert the password of the second (index 1) user
(assoc-in users [1 :password] "nhoJ")
;;=> [{:name "James", :age 26} {:password "nhoJ", :name "John", :age 43}]

;; create a third (index 2) user
;; Also (assoc m 2 {...}) or (conj m {...})
(assoc-in users [2] {:name "Jack" :age 19})  
;;=> [{:name "James", :age 26} {:name "John", :age 43} {:name "Jack", :age 19}]

;; From http://clojure-examples.appspot.com/clojure.core/assoc-in
            
                ;; can be used to update a mutable item.
(def ppl (atom {"persons" {"joe" {:age 1}}}))
(swap! ppl assoc-in ["persons" "bob"] {:age 11})

@ppl
;;=> {"persons" {"joe" {:age 1}, "bob" {:age 11}}}
            
                ;; be careful with that empty path sequence, it's seldom what you want
(assoc-in {} [] {:k :v})
;;=> {nil {:k :v}}

;; In general, you find that for a non-empty path
;;   (get-in (assoc-in m path v) path) 
;; is equal to v.
;; Surprisingly this does not hold true in case of an empty path.
            
                ;; another example of updating a mutable item.
;; this time the first key is to a map and the second to a vector.
(def foo (atom {:users [{:a "a"} {:b "b"}]}))
(swap! foo assoc-in [:users 2] {:c "c"})
;;=> {:users [{:a "a"} {:b "b"} {:c "c"}]}


            
                ;; assoc-in into a nested map structure
(def foo {:user {:bar "baz"}})
(assoc-in foo [:user :id] "some-id")
;;=> {:user {:bar "baz", :id "some-id"}}

            
                (assoc-in {} [:cookie :monster :vocals] "Finntroll")
; => {:cookie {:monster {:vocals "Finntroll"}}}

(get-in {:cookie {:monster {:vocals "Finntroll"}}} [:cookie :monster])
; => {:vocals "Finntroll"}

(assoc-in {} [1 :connections 4] 2)
; => {1 {:connections {4 2}}}

;; from http://www.braveclojure.com/functional-programming/
            
                ;; assoc-in can be used on vectors too

(def row 0)
(def col 0)

(assoc-in [[1 1 1]
           [1 1 1]
           [1 1 1]] [row col] 0)
; => [[0 1 1][1 1 1][1 1 1]]

(get-in [[0 1 1]
         [1 1 1]
         [1 1 1]] [row col])
; => 0
            
                ; Playing around with assoc-in

(assoc-in {:person {:name "Mike"}} [:person :name] "Violet")
; => {:person {:name "Violet"}}

(assoc-in {:person {:name "Mike"}} [:person] "Violet")
; => {:person "Violet"}

(assoc-in [{:person {:name "Mike"}}] [0 :person :name] "Violet")
; => [{:person {:name "Violet"}}]

(assoc-in [{:person {:name ["Mike"]}}] [0 :person :name 1] "Smith")
; => [{:person {:name ["Mike" "Smith"]}}]

(assoc-in [{:person {:name ["Mike"]}}] [0 :person :name 2] "Smith")
; => IndexOutOfBoundsException