简体   繁体   中英

Clojure - How merge two/more maps into a single map which have the same value for certain key(s)

I am learning how to idiomatically destruct data structures in Clojure and currently have the following example data

Data:

(def data [
{:category "A", :vertical_name "One", :vertical_id 11}
{:category "B", :vertical_name "Two", :vertical_id 12}
{:category "A", :vertical_name "Three", :vertical_id 13}
{:category "C", :vertical_name "Four", :vertical_id 14}
])

I want to merge two/more maps into a single map which belong to the same Category in the data above,

Expected Output:

{{:category "A", :vertical [{:vertical_id 11, :vertical_name "One"}{:vertical_id 13,  :vertical_name "Three"}]}
{:category "B", :vertical {:vertical_id 12, :vertical_name "Two"}}
{:category "C", :vertical {:vertical_id 14, :vertical_name "Four"}}}

I have tried group-by which gives me

{"A" [{:category "A", :vertical_name "One", :vertical_id 11} {:category "A", :vertical_name "Three", :vertical_id 13}],
"B" [{:category "B", :vertical_name "Two", :vertical_id 12}],
"C" [{:category "C", :vertical_name "Four", :vertical_id 14}]}

But this has a lot of redundant information, for example :category "A" is present in all the maps and the format of the output isn't the way I want it.

Thanks in advance for the help.

user> (->> data
        (group-by :category)
        (map (fn [[k v]]
                 (let [vertical (map #(dissoc % :category) v)
                       vertical (if (< (count vertical) 2)
                                  (first vertical)
                                  (vec vertical))]
                   {:category k
                    :vertical vertical})))
        set)

#{{:category "A", :vertical [{:vertical_name "One", :vertical_id 11} {:vertical_name "Three", :vertical_id 13}]} {:category "B", :vertical {:vertical_name "Two", :vertical_id 12}} {:category "C", :vertical {:vertical_name "Four", :vertical_id 14}}}

This is the format you describe, but for most usage it would be worse than the output group-by provides. Unlike the group-by result, you cannot efficiently look up a given category as the size of the result scales. Further, unlike the result of group-by , sometimes the :vertical key has a collection, and sometimes a single element, and this is a piece of complexity offloaded onto any other code that accesses this data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM