I am trying idiomatically merge multiple maps into a single map using clojure.
Input
{:a 1 :b "a"}
{:a 2 :b "b"}
{:a 3 :b "c"}
{:a 4 :b "a"}
Expected
{:a #{1,2,3,4}, :b #{"a" "b" "c"}}
The values for each key are converted into a set of values in the original maps.
I'd use merge-with
, using a pre-built structure that contains empty sets:
(def data [{:a 1 :b "a"}
{:a 2 :b "b"}
{:a 3 :b "c"}
{:a 4 :b "a"}])
(let [base {:a #{} :b #{}}]
(apply merge-with conj base data))
=> {:a #{1 2 3 4}, :b #{"a" "b" "c"}}
The trick of using empty sets in the base map is so that conj
has a concrete object to work upon, and hence works correctly.
merge-with
can be used for this like:
(def d [{:a 1 :b "a"}
{:a 2 :b "b"}
{:a 3 :b "c"}
{:a 4 :b "a"}])
(def initial (into {} (map #(vector %1 []) (keys (apply merge d)))))
(into {} (map (fn [[a b]] [a (set b)])
(apply merge-with (fn [a b] (conj a b)) initial d)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With