Reputation: 133
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.
Upvotes: 1
Views: 167
Reputation: 20194
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.
Upvotes: 1