Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure, merging two array of maps

Tags:

clojure

I have two arrays of maps

1st is [{:a 1 :b 2 :d 6} {:a 2 :b 2} {:a 7 :b 7}]

2nd is [{:a 3 :c 3 :e 9 :y 7} {:a 2 :b 6 :c 8}]

depending on the value of a i.e. if its matches in 2nd array the '2nd map' should be merged with '1st map' and the resultant array of maps should be

Res should be [{:a 1 :b 2 :d 6} {:a 2 :b 6 :c 8} {:a 7 :b 7} {:a 3 :c 3 :e 9 :y 7}]

Can anyone help me on this. Thanks in advance.

like image 679
Avi Avatar asked Apr 18 '12 12:04

Avi


2 Answers

Here you go:

user> (def xs [{:a 1 :b 2 :d 6} {:a 2 :b 2} {:a 7 :b 7}])
#'user/xs
user> (def ys  [{:a 3 :c 3 :e 9 :y 7} {:a 2 :b 6 :c 8}])
#'user/ys
user> (for [[a ms] (group-by :a (concat xs ys))] (apply merge ms))
({:a 1, :b 2, :d 6} {:a 2, :c 8, :b 6} {:a 7, :b 7} {:y 7, :a 3, :c 3, :e 9})
like image 54
Marko Topolnik Avatar answered Sep 29 '22 09:09

Marko Topolnik


This data structure looks very unwieldy to me nevertheless here's my take:

(defn key-by-a [coll]
  "Convert a list of maps to a map of maps keyed by their vals at :a"
  (apply hash-map (mapcat (juxt :a identity) coll)))

(defn merge-map-lists [l1 l2]
  (->> [l1 l2]
    (map key-by-a)
    (apply merge-with merge)
    (vals)))

One thing it doesn't do is maintaining order of the input lists but since it is not clear which list decides (both might have same keys in different orders) I left that out.

like image 30
Rafał Dowgird Avatar answered Sep 29 '22 09:09

Rafał Dowgird