Constructs an array-map. If any keys are equal, they are handled as if by repeated uses of assoc.
user=> (array-map :a 10) {:a 10} user=> (array-map :a 10 :b 20) {:a 10 :b 20} user=> (apply array-map [:a 10 :b 20 :c 30]) {:a 10 :b 20 :c 30} user=> (apply assoc {} [:a 10 :b 20 :c 30]) ;same result using assoc {:a 10 :b 20 :c 30}
user=> (keys (assoc (array-map :foo 10 :bar 20) :baz 30)) (:baz :foo :bar) ; baz is first; :foo and :bar follow the order given to array-map ;; My results have consistently been different from what's listed above. user=> (keys (assoc (array-map :foo 10 :bar 20) :baz 30)) ; => (:foo :bar :baz) user=> (assoc (array-map :foo 10 :bar 20) :baz 30) ; => {:foo 10, :bar 20, :baz 30} user=> *clojure-version* ; => {:major 1, :minor 8, :incremental 0, :qualifier nil} ;; As long as I have an array map, new items get added to the end, not ;; the beginning.
;; Sometimes Clojure will automatically choose between a hash map and ;; an array map. What's the rule? Let's try a few experiments. ;; Start with a quick way to make a map with N items. user=> (defn make-map [count] (zipmap (range count) (range count))) ;; => #'user/make-map user=> (make-map 3) ;; => {0 0, 1 1, 2 2} ;; Try a few maps. The cutoff seems to be 9.5. If you have fewer than ;; 9.5 items you get an array map. If you have more than 9.5 items you ;; get a hash map. user=> (type (make-map 8)) ;; => clojure.lang.PersistentArrayMap user=> (type (make-map 9)) ;; => clojure.lang.PersistentArrayMap user=> (type (make-map 10)) ;; => clojure.lang.PersistentHashMap user=> (type (make-map 11)) ;; => clojure.lang.PersistentHashMap ;; Using assoc we get similar results. 9 or fewer items yields an array ;; map. 10 or more yields a hash map. user=> (type (assoc (make-map 9) :x 1)) ; 10 items -> hash map. ;; => clojure.lang.PersistentHashMap user=> (type (assoc (make-map 8) :x 1)) ; 9 items -> array map. ;; => clojure.lang.PersistentArrayMap user=> (type (assoc (make-map 8) :x 1 :y 2)) ; 10 items -> hash map. ;; => clojure.lang.PersistentHashMap user=> (type (assoc (assoc (make-map 8) :x 1) :y 2)) ; 10 items -> hash map. ;; => clojure.lang.PersistentHashMap ;; But when we use { and } to create a map, the cutoff seems to move to 8.5. ;; A map with 9 items created with assoc or zipmap would be an array map, ;; but a map with 9 items created by { } is a hash map. user=> (type {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7}) ; 8 items -> array map. ;; => clojure.lang.PersistentArrayMap user=> (type {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7, 8 8}) ; 9 items -> hash ;; => clojure.lang.PersistentHashMap ;; Calling dissoc on an array map always yields an array map, regardless of ;; the size of the map. ;; Let's start by making a large array map then remove a few items. This will ;; give us array maps larger than you could create with assoc. user=> (def array20 (apply array-map (range 40))) ;; => #'user/array20 user=> (type array20) ;; => clojure.lang.PersistentArrayMap user=> (type (dissoc array20 6)) ;; => clojure.lang.PersistentArrayMap user=> (count (dissoc array20 6)) ;; => 19 user=> (type (dissoc array20 6 2)) ;; => clojure.lang.PersistentArrayMap user=> (count (dissoc array20 6 2)) ;; => 18 ;; Calling dissoc on a hash map always yields another hash map, regardless ;; of the size of the map. ;; Let's start by making a large hash map then remove a lot of items. This ;; will give us hash maps smaller than you could create with assoc. user=> (type (make-map 40)) ;; => clojure.lang.PersistentHashMap user=> (type (apply dissoc (make-map 40) (range 1 80))) ;; => clojure.lang.PersistentHashMap user=> (count (apply dissoc (make-map 40) (range 1 80))) ;; => 1 user=> (apply dissoc (make-map 40) (range 1 80)) ;; => {0 0} user=> (type (apply dissoc (make-map 40) (range 0 80))) ;; => clojure.lang.PersistentHashMap user=> (count (apply dissoc (make-map 40) (range 0 80))) ;; => 0 user=> (apply dissoc (make-map 40) (range 0 80)) ;; => {}
;; Maybe you generated a sequence of kv pairs (def kvs [[:a 1] [:b 2] [:c 3] [:d 4] [:e 5] [:f 6] [:g 7] [:h 8] [:i 9]]) ;; A naïve approach to putting into an array-map… (into (array-map) kvs) ;; => {:e 5, :g 7, :c 3, :h 8, :b 2, :d 4, :f 6, :i 9, :a 1} ;; …loses order (type *1) ;; => clojure.lang.PersistentHashMap ;; This approach… (apply array-map (sequence cat kvs)) ;; => {:a 1, :b 2, :c 3, :d 4, :e 5, :f 6, :g 7, :h 8, :i 9} ;; …preserves order (type *1) ;; => clojure.lang.PersistentArrayMap
assoc[iate]. When applied to a map, returns a new map of the same (hashed/sorted) type, that con...
keyval => key val Returns a new hash map with supplied mappings. If any keys are equal, they ar...
keyval => key val Returns a new sorted map with supplied mappings. If any keys are equal, they ...
The definition is kind of short, IMO. More descriptively, array-map
creates a mapping with arrays being the keys and the values. It doesn't seem like array-map
cares whether or not the keys/values are arrays, although it doesn't seem to like sequences.
An array-map
maintains the insertion order of the keys. Look up is linear, which is not a problem for small maps (say less than 10 keys). If your map is large, you should use hash-map
instead.
When you assoc
onto an existing array-map, the result is a new array-map with the new key as the first key. The rest of the keys are in the same order as the original. Functions such as seq
and keys
will respect the key order.
Note that assoc
will decide to return a hash-map if the result is too big to be efficient.