Search code examples
clojure

GROUP BY and Aggregation on Vector of maps - Clojure


I have data that looks like this

(def a [{:firmAccount "MSFT" :Val 10  :PE 3 }  
        {:firmAccount "MSFT" :Val 15  :PE 4} 
        {:firmAccount "GOG" :Val 15 :PE 3} 
        {:firmAccount "YAH" :Val 8 :PE 1}])

I want to group by on :firmAccount and then SUM the :Val and :PE for each firm account and get something like

 [{:firmAccount "MSFT" :Val 25 :PE 7}
  {:firmAccount "GOG" :Val 15 :PE 3}    
  {:FirmAccount "YAH" :Val 8 :PE 1}]

It is really a trivial thing and in SQL I would not even think twice but since I am learning clojure please bear with me


Solution

  • Clojure.core has a built-in group-by function. The solution becomes a little ugly by the presence of both text and int vals in the maps.

    (for [m (group-by :firmAccount a)]
       (assoc (apply merge-with + (map #(dissoc % :firmAccount) (val m)))
              :firmAccount (key m)))