TL;DR(太长不看)
update-vals
和 update-keys
主要用于处理基于某个标识符键的同类数据映射。
https://clojure.atlassian.net/browse/CLJ-2651
https://clojure.atlassian.net/browse/CLJ-1959
但是,在核心库中没有函数可以直接从同质数据的序列中生成这样的映射。我想可能会有很多方法来做到这一点,例如
(into {} (map (juxt f identity)) coll) ; credit Sean Corfield
(persistent! (reduce #(assoc! %1 (f %2) %2) (transient {}) coll)) ; from Medley
(update-vals first (group-by f coll))
但我不知道哪种方法是最高效的。所以我想要知道,在核心库中是否有一个key-by
函数可以以良好的性能生产此类映射?
Clojure 1.11 引入了 update-keys
和 update-vals
,我开始使用它们来替代我们手写的 map-vals
等。
然而,我仍然不确定如何最佳地创建update-keys
和 update-vals
可操作的映射。通常,我会从数据库中检索一系列同质映射,如下所示
[{:id 1 :name "brandon"}
{:id 2 :name "brenda"}
{:id 3 :name "kelly"}]
并使用 (key-by :id coll)
或 (index-by :id coll)
函数将其转换为
{1 {:id 1 :name "brandon"}
2 {:id 2 :name "brenda"}
3 {:id 3 :name "kelly"}}
但是,如何最好地实现这一点?update-vals
允许
(defn key-by
[f coll]
(update-vals first (group-by f coll)))
但这些集合通常很大,人们希望能够获得很好的性能。在Medley中,index-by
被编写为如下
(defn index-by
[f coll]
(persistent! (reduce #(assoc! %1 (f %2) %2) (transient {}) coll)))
它看起来更快,这是我永远无法想出来的。所以我不禁怀疑,当引入 update-keys
和 update-vals
时,难道 key-by
(这个名字对我来说听起来更好)是Clojure核心库中的一个缺失的部分吗?