Created
October 21, 2023 02:52
-
-
Save jplaza/dfa624a8f9c9effc8c5edee74c99a6d2 to your computer and use it in GitHub Desktop.
Aggregate data in the form of a list of hash maps in Clojure. Inspired by SQL GROUP BY and aggregate functions like SUM and MAX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn aggregate-data | |
"data - collection of hash-maps to aggregate | |
group-key - vector of keys to group hash-maps | |
aggregates - vector of vectors of key, aggregate fn and optionally a new | |
name for this key e.g. | |
[[+ :amount :stock] | |
[max :date :latest-tx-date]] | |
Aggregate functions receive variable arguments" | |
[data group-keys aggregates] | |
(->> data | |
(group-by (fn [item] (select-keys item group-keys))) | |
(map (fn [[_group-key items]] | |
(merge (select-keys (first items) group-keys) | |
(into {} | |
(map (fn [[aggregate-fn aggregate-key rename]] | |
(vector (or rename aggregate-key) | |
(apply aggregate-fn | |
(->> (map aggregate-key items) | |
(remove nil?))))) | |
aggregates))))))) | |
;; usage | |
(def inventory-txs | |
[{:id "tx1" | |
:pid "p1" | |
:desc "Inventory input Product P1" | |
:amount 10 | |
:created 1673308800000} | |
{:id "tx2" | |
:pid "p1" | |
:desc "Inventory output Product P1" | |
:amount -5 | |
:created 1674172800000} | |
{:id "tx3" | |
:pid "p2" | |
:desc "Invoice input Product P2" | |
:amount 8 | |
:created 1673395200000}]) | |
(aggregate-data inventory-txs [:pid] | |
[[+ :amount] | |
[max :created :latest-tx-date]]) | |
;; result | |
({:pid "p1", :amount 5, :latest-tx-date 1674172800000} | |
{:pid "p2", :amount 8, :latest-tx-date 1673395200000}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment