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))
但是我不知道哪个是最高效的。所以我很好奇,在引入update-keys
和update-vals
时,key-by
函数是否在Clojure核心中留下了缺失的一环?
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)))
它看起来似乎更快,这是我永远也想不到的。所以我免不了要 wonder,是否在引入update-keys
和update-vals
时,缺少了Clojure核心中的key-by
(这个名字对我来说听起来更好)这一部分?