Clojure中实现数据集动态分组的技术问询
动态分组解决方案
直接上可运行的动态分组函数,完全适配你需要的任意分组键组合:
(defn dynamic-group [group-keys rows] (let [group-fn (apply juxt group-keys) grouped (group-by group-fn rows)] (map (fn [[grp-tuple values]] (merge (zipmap group-keys grp-tuple) {:value-sums (reduce + (map :value values)) :values values})) grouped)))
关键逻辑说明
- 动态分组键生成:
apply juxt group-keys会根据传入的分组键列表(比如[:year :week :name])自动生成对应的分组提取函数,替代你原代码里硬编码的(juxt :week :year),实现真正的动态性。 - 分组结果转键值对:
zipmap group-keys grp-tuple把分组得到的元组(比如(2023 "Name1"))和分组键列表配对成键值对,不用再手动写(first grp-key)这类硬编码逻辑。 - 正确求和:
reduce + (map :value values)先提取分组内所有数据的:value,再求和,修正了你原代码里求和逻辑的错误。
测试示例
用你的测试数据验证不同分组场景:
- 按
[:year :month]分组:
(dynamic-group [:year :month] test-data) ; 输出结果: ({:year 2023, :month 1, :value-sums 8, :values [{:year 2023, :quarter 1, ...}, {:year 2023, :quarter 1, ...}]})
- 按
[:year :name]分组:
(dynamic-group [:year :name] test-data) ; 输出结果: ({:year 2023, :name "Name1", :value-sums 5, :values [{:year 2023, :quarter 1, ...}]} {:year 2023, :name "Name2", :value-sums 3, :values [{:year 2023, :quarter 1, ...}]})
- 仅按
[:name]分组:
(dynamic-group [:name] test-data) ; 输出结果: ({:name "Name1", :value-sums 5, :values [{:year 2023, :quarter 1, ...}]} {:name "Name2", :value-sums 3, :values [{:year 2023, :quarter 1, ...}]})
如果不需要保留原数据列表 :values,直接从merge里删掉对应的键即可;要是需要其他聚合逻辑(比如求平均值),替换reduce + (map :value values)部分就行。
内容的提问来源于stack exchange,提问作者triplem
相关产品推荐
相关产品推荐

