You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现从值到关键字的数据转换?(Clojure映射场景)

问题

现有如下Clojure映射数据:

({:year 2023, :month 4, :type TypeA, :cat CatA, :amount 62.5} 
 {:year 2023, :month 4, :type TypeB, :cat CatB, :amount 45.25} 
 {:year 2023, :month 4, :type TypeC, :cat CatA, :amount 40.0} 
 {:year 2023, :month 5, :type TypeA, :cat CatA, :amount 52.75} 
 {:year 2023, :month 5, :type TypeC, :cat CatA, :amount 14.0})

需要实现两种聚合转换:

  1. 按type字段聚合:将type的取值转为关键字,同年月的金额合并,缺失的类型金额填0
    ({:year 2023, :month 4, :typeA 62.5, :typeB 45.25, :typeC 40.0}
     {:year 2023, :month 5, :typeA 52.75, :typeB 0, :typeC 14.0})
    
  2. 按cat字段聚合:逻辑同上,结果如下
    ({:year 2023, :month 4, :catA 102.5, :catB 45.25}
     {:year 2023, :month 5, :catA 66.75, :catB 0})
    

额外要求:type和cat字段需支持灵活扩展,不能硬编码字段名称。

解决方案

可以实现一个通用聚合函数,通过传入分组字段关键字(如:type或:cat)实现灵活扩展:

(defn aggregate-by-field [data group-field]
  ;; 提取分组字段的所有唯一取值,并转为对应关键字(例:TypeA → :typeA)
  (let [all-values (->> data (map group-field) distinct (map #(keyword (name %))))
        ;; 按年月分组,计算每组内各取值的金额总和
        grouped (->> data
                     (group-by (juxt :year :month))
                     (map (fn [[[year month] items]]
                            (merge {:year year :month month}
                                   (reduce (fn [acc item]
                                             (let [k (keyword (name (group-field item)))
                                                   amt (:amount item)]
                                               (update acc k (fnil + 0) amt)))
                                           {}
                                           items)))))]
    ;; 补全每组缺失的取值,金额设为0
    (map #(merge (zipmap all-values (repeat 0)) %) grouped)))

使用示例

(def sample-data
  '({:year 2023, :month 4, :type TypeA, :cat CatA, :amount 62.5} 
    {:year 2023, :month 4, :type TypeB, :cat CatB, :amount 45.25} 
    {:year 2023, :month 4, :type TypeC, :cat CatA, :amount 40.0} 
    {:year 2023, :month 5, :type TypeA, :cat CatA, :amount 52.75} 
    {:year 2023, :month 5, :type TypeC, :cat CatA, :amount 14.0}))

;; 按type聚合
(aggregate-by-field sample-data :type)

;; 按cat聚合
(aggregate-by-field sample-data :cat)

代码说明

  1. 提取唯一取值:从全量数据中取出指定分组字段的所有值,去重后转为对应的关键字,确保覆盖所有可能的分组项。
  2. 年月分组求和:用group-by按年月组合分组,对每组内的项按分组字段累加金额,生成基础聚合结果。
  3. 补全缺失项:生成包含所有分组项、金额为0的映射,与每组聚合结果合并,保证所有分组项都存在,缺失项金额自动补0。

该实现无需硬编码任何分组字段的具体取值,新增其他分组字段时直接传入对应关键字即可。

内容的提问来源于stack exchange,提问作者triplem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 19:23:11