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
And for completeness here's an alternate version that uses map:
(map (fn [[firmAccount vals]]
{:firmAccount firmAccount
:Val (reduce + (map :Val vals))
:PE (reduce + (map :PE vals))})
(group-by :firmAccount a))
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)))
Try creating a new map array or map of maps with the same structure. You can write a function to add elements to this new map that sums that fields if the :firm-account exists. Maybe a map like this?
(def a {"MSFT" {:Val 25 :PE 7 }
"GOG" {:Val 15 :PE 3}
"YAH" {:Val 8 :PE 1}})
With a personalized add function like:
(add-to-map [element map]
(if (contains? (find-name element))
{map (add-fields element (find (find-name element)))}
{map element}))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With