假设我有以下数据:
({: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})
我想按类型或按猫将其转换为以下内容:
({:year 2023, :month 4, :typeA 62.5, :typeB 42.25, :typeC 40.0}
{:year 2023, :month 5, :typeA 52.75, :typeB 0, :typeC 14.0}}
或猫:
({:year 2023, :month 4, :catA 102.5, :catB 42.25}
{:year 2023, :month 5, :catA 52.75, :catB 14.0}}
我对不同的和嵌套的地图进行了一些尝试,但没有找到有效的解决方案。
奖金: 类型和猫应该是灵活的,通过名称硬编码来引用它们是不安全的。
另外,一次通过(我猜是一个更简单的选项):
(defn process [k data]
(vals (reduce
#(let [y-m (select-keys %2 [:year :month])]
(update % y-m (fnil assoc y-m) (keyword (k %2)) (:amount %2)))
nil
data)))
user> (process :type data)
;;=> ({:year 2023, :month 4, :TypeA 62.5, :TypeB 45.25, :TypeC 40.0}
;; {:year 2023, :month 5, :TypeA 52.75, :TypeC 14.0})
user> (process :cat data)
;;=> ({:year 2023, :month 4, :CatA 40.0, :CatB 45.25}
;; {:year 2023, :month 5, :CatA 14.0})
结果似乎已经很接近了
(let [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})
key-fields [:year :month]
k-field :cat
;k-field :type
v-field :amount]
(->> data
(group-by #(select-keys % key-fields))
(mapv (fn [[k ms]]
(reduce (fn [k m]
(let [;; Not sure if you need to make the first character lower-case here.
f (keyword (k-field m))]
(assoc k f (v-field m))))
k ms)))))
它不会为缺失值添加零,但我认为通常最好不要添加它们。相反,此代码的客户可以决定如何处理它们。
相同,但带有换能器:
(defn transform [key]
(xf/into-by-key [] (fn-> (select-keys [:year :month])) identity into
(comp
(xf/sort-by key)
(xf/into-by-key [] (comp keyword key) :amount (xf/reduce +)))))
(into [] (xf/transjuxt {:type (transform :type)
:cat (transform :cat)}) data)
=>
[{:type
[{:year 2023, :month 4, :TypeA 62.5, :TypeB 45.25, :TypeC 40.0}
{:year 2023, :month 5, :TypeA 52.75, :TypeC 14.0}],
:cat
[{:year 2023, :month 4, :CatA 102.5, :CatB 45.25}
{:year 2023, :month 5, :CatA 66.75}]}]
xf
被[net.cgrand.xforms :as xf]