(merge-with f & maps)
Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter).
(merge-with into
\t {"Lisp" ["Common Lisp" "Clojure"]
\t "ML" ["Caml" "Objective Caml"]}
\t {"Lisp" ["Scheme"]
\t "ML" ["Standard ML"]})
;;=> {"Lisp" ["Common Lisp" "Clojure" "Scheme"], "ML" ["Caml" "Objective Caml" "Standard ML"]}
;; merge two maps using the addition function
(merge-with +
{:a 1 :b 2}
{:a 9 :b 98 :c 0})
;;=> {:c 0, :a 10, :b 100}
;; 'merge-with' works with an arbitrary number of maps:
(merge-with +
{:a 1 :b 2}
{:a 9 :b 98 :c 0}
{:a 10 :b 100 :c 10}
{:a 5}
{:c 5 :d 42})
;;=> {:d 42, :c 15, :a 25, :b 200}
;; Use union to merge sets of elements
(use 'clojure.set)
(merge-with union
{:a #{1 2 3}, :b #{4 5 6}}
{:a #{2 3 7 8}, :c #{1 2 3}})
;;=> {:c #{1 2 3}, :a #{1 2 3 7 8}, :b #{4 5 6}}
;; Demonstrating difference between merge and merge-with
;; For merge the value from the right-most map wins:
(merge {:a 1} {:a 2} {:a 3})
;;=> {:a 3}
;; while for merge-with values are merged (with function + in this example):
(merge-with + {:a 1} {:a 2} {:a 3})
;;=> {:a 6}
;; Use merge-with and merge to merge values that are one level deep maps.
(merge-with merge {:x {:y 1}} {:x {:z 2}})
;;=> {:x {:z 2, :y 1}}
;; Deeper maps are not merged:
(merge-with merge {:x {:y {:a 1}}} {:x {:y {:b 2}}})
;;=>{:x {:y {:b 2}}}
;;Use into to avoid losing the shape (i.e. a vector) of the original data:
(merge-with into
\t {"Lisp" ["Common Lisp" "Clojure"]
\t "ML" ["Caml" "Objective Caml"]}
\t {"Lisp" ["Scheme"]
\t "ML" ["Standard ML"]})
;;=> {"Lisp" ["Common Lisp" "Clojure" "Scheme"], "ML" ["Caml" "Objective Caml" "Standard ML"]}
;;No need to use type-specific verbs such as union:
(merge-with into
{:a #{1 2 3}, :b #{4 5 6}}
{:a #{2 3 7 8}, :c #{1 2 3}})
;;=> {:c #{1 2 3}, :a #{1 2 3 7 8}, :b #{4 5 6}}
;; Note that merge-with is fundamentally additive, which can have unintuitive
;; consequences if you are using a subtractive operation.
(require '[clojure.set :as set])
;; Subtract members of one set from another with the same keys:
(merge-with set/difference {:a #{1 2 3}} {:a #{1}})
;;=> {:a #{3 2}}
(merge-with set/difference {:a #{1 2 3} :b #{2}} {:a #{1} :b #{4}})
;;=> {:a #{3 2}, :b #{2}}
;; If a key in the second map doesn't occur in the first, (merge-with) will
;; simply copy it as in (merge), and the passed-in function will not be called:
(merge-with set/difference {:a #{1 2 3}} {:a #{1} :z #{4}})
;;=> {:a #{3 2}, :z #{4}}
;; The solution in this case is to ensure that both maps have the same keys:
(merge-with set/difference {:a #{1 2 3} :z #{}} {:a #{1} :z #{4}})
;;=> {:a #{3 2}, :z #{}}