Clojure, merging two array of maps

匿名 (未验证) 提交于 2019-12-03 02:26:02

问题:

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.

回答1:

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}) 


回答2:

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.



回答3:

maybe clojure.set/join is what you want:

here is the docs of clojure.set/join:

user=> (def animals #{{:name "betsy" :owner "brian" :kind "cow"}                       {:name "jake"  :owner "brian" :kind "horse"}                       {:name "josie" :owner "dawn"  :kind "cow"}})  user=> (def personalities #{{:kind "cow" :personality "stoic"}                             {:kind "horse" :personality "skittish"}}) #'user/personalities user=> (join animals personalities)  #{{:owner "dawn",  :name "josie", :kind "cow",   :personality "stoic"}   {:owner "brian", :name "betsy", :kind "cow",   :personality "stoic"}   {:owner "brian", :name "jake",  :kind "horse", :personality "skittish"}}  user=> (join animals personalities) #{{:kind "horse", :owner "brian", :name "jake", :species "cow", :personality "stoic"}   {:kind "cow", :owner "dawn", :name "josie", :species "cow", :personality "stoic"}   {:kind "horse", :owner "brian", :name "jake", :species "horse", :personality "skittish"}   {:kind "cow", :owner "brian", :name "betsy", :species "cow", :personality "stoic"}   {:kind "cow", :owner "dawn", :name "josie", :species "horse", :personality "skittish"}   {:kind "cow", :owner "brian", :name "betsy", :species "horse", :personality "skittish"}}   ;; Notice that "Jake" is both a horse and a cow in the first line. That's  ;; likely not what you want. You can tell `join` to only produce output  ;; where the `:kind` value is the same as the `:species` value like this:  user=> (join animals personalities {:kind :species}) #{{:kind "cow", :owner "dawn", :name "josie", :species "cow", :personality "stoic"}   {:kind "horse", :owner "brian", :name "jake", :species "horse", :personality "skittish"}   {:kind "cow", :owner "brian", :name "betsy", :species "cow", :personality "stoic"}} 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!