在Clojure中,如何分组元素?

vie*_*bel 10 group-by clojure aggregate-functions

在clojure中,我想聚合这些数据:

(def data [[:morning :pear][:morning :mango][:evening :mango][:evening :pear]])
(group-by first data)
;{:morning [[:morning :pear][:morning :mango]],:evening [[:evening :mango][:evening :pear]]}
Run Code Online (Sandbox Code Playgroud)

我的问题是:evening:morning是多余的.相反,我想创建以下集合:

([:morning (:pear :mango)] [:evening (:mango :pear)])
Run Code Online (Sandbox Code Playgroud)

我提出了:

(for [[moment moment-fruit-vec] (group-by first data)] [moment (map second moment-fruit-vec)])
Run Code Online (Sandbox Code Playgroud)

有更惯用的解决方案吗?

Mik*_*edt 5

我遇到过类似的分组问题.通常我最终将merge-with或update-in插入到某个seq处理步骤中:

(apply merge-with list (map (partial apply hash-map) data))
Run Code Online (Sandbox Code Playgroud)

你得到一张地图,但这只是一对键值对:

user> (apply merge-with list (map (partial apply hash-map) data))
{:morning (:pear :mango), :evening (:mango :pear)}
user> (seq *1)
([:morning (:pear :mango)] [:evening (:mango :pear)])
Run Code Online (Sandbox Code Playgroud)

但是,如果每个键出现两次,此解决方案只会获得您想要的结果.这可能更好:

(reduce (fn [map [x y]] (update-in map [x] #(cons y %))) {} data)
Run Code Online (Sandbox Code Playgroud)

这两种感觉都"更具功能性",但也有点令人费解.不要太快解除您的解决方案,它易于理解且功能足够.