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 核心库中缺失的一块呢?