'clojure: how can I merge these two maps?
I have one map that looks like
{:a {:b {:c {:d [[1 2 3]]}
:e "Hello"}}}
and another map that looks like {:a {:b {:c {:d [[4 5 6]]}}}}. How can I merge these two maps so that the result looks like this?
{:a {:b {:c {:d [[1 2 3] [4 5 6]]}
:e "Hello"}}}
Solution 1:[1]
You can use deep-merge-with from the deprecated clojure-contrib.map-utils:
(defn deep-merge-with [f & maps]
(apply
(fn m [& maps]
(if (every? map? maps)
(apply merge-with m maps)
(apply f maps)))
maps))
(def m1
{:a {:b {:c {:d [[1 2 3]]}
:e "Hello"}}})
(def m2
{:a {:b {:c {:d [[4 5 6]]}}}})
(deep-merge-with into m1 m2)
;; => {:a {:b {:c {:d [[1 2 3] [4 5 6]]}
;; :e "Hello"}}}
Solution 2:[2]
For such a simple use-case, you might choose to stick with core Clojure functions:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(let [x {:a {:b {:c {:d [[1 2 3]]}
:e "Hello"}}}
y {:a {:b {:c {:d [[4 5 6]]}}}}
yseq (get-in y [:a :b :c :d])
r1 (update-in x [:a :b :c :d] into yseq)
r2 (update-in x [:a :b :c :d] #(into % yseq)) ]
(is= r1 r2
{:a {:b {:c {:d [[1 2 3]
[4 5 6]]},
:e "Hello"}}})))
As shown for r2, I sometimes think it is clearer to use a self-contained closure function to explicitly show where the old value % is being used. I am often even more explicit, writing the r2 closure as:
(fn [d-val]
(into d-val yseq))
instead of using the #(...) reader macro.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Erwin Rooijakkers |
| Solution 2 |
