I need to convert the following data:
[{["A" 1] [{:ms "A", :s 1, :v 15}], ["A" 2] [{:ms "A", :s 2, :v 18}], ["A" 4] [{:ms "A", :s 4, :v 19}]}
{["A" 1] [{:ms "A", :s 1, :v2 5}], ["A" 2] [{:ms "A", :s 2, :v2 8}], ["B" 4] [{:ms "B", :s 4, :v2 9}]}]
to:
[{:ms "A", :s 1, :v 15, :v2 5} {:ms "A", :s 2, :v 18, :v2 8} {:ms "A", :s 4, :v 19} {:ms "B", :s 4, :v2 9}]
I'm struggling with the implementation, any help would be appreciated :)
this would work:
(def data [{["A" 1] [{:ms "A", :s 1, :v 15}],
["A" 2] [{:ms "A", :s 2, :v 18}],
["A" 4] [{:ms "A", :s 4, :v 19}]}
{["A" 1] [{:ms "A", :s 1, :v2 5}],
["A" 2] [{:ms "A", :s 2, :v2 8}],
["B" 4] [{:ms "B", :s 4, :v2 9}]}])
(map (partial apply merge) (vals (apply merge-with concat data)))
here's a step by step explaination:
first of all we merge all the toplevel maps, concatenating values for equal keys:
(apply merge-with concat data)
;;=> {["A" 1] ({:ms "A", :s 1, :v 15} {:ms "A", :s 1, :v2 5}),
;; ["A" 2] ({:ms "A", :s 2, :v 18} {:ms "A", :s 2, :v2 8}),
;; ["A" 4] [{:ms "A", :s 4, :v 19}],
;; ["B" 4] [{:ms "B", :s 4, :v2 9}]}
then for every value in the map we should perform the merge to one map:
(apply merge '({:ms "A", :s 1, :v 15} {:ms "A", :s 1, :v2 5}))
;;=> {:ms "A", :s 1, :v 15, :v2 5}
so we should use map
:
(map (partial apply merge) (vals (apply merge-with concat data)))
;;=> ({:ms "A", :s 1, :v 15, :v2 5}
;; {:ms "A", :s 2, :v 18, :v2 8}
;; {:ms "A", :s 4, :v 19}
;; {:ms "B", :s 4, :v2 9})