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 核心中的缺失环节?