2024 Clojure状态调查!分享您的想法。

欢迎!请参阅关于页面,以了解更多关于此功能的信息。

+6
Clojure
重分类

TL;DR(太长不看)

update-valsupdate-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-keysupdate-vals,我开始使用它们来替代我们手写的 map-vals 等。

然而,我仍然不确定如何最佳地创建update-keysupdate-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-keysupdate-vals 时,难道 key-by(这个名字对我来说听起来更好)是Clojure核心库中的一个缺失的部分吗?

有一个请求功能的推广,我还没有看到有人提到过,它可以涵盖 `group-by` 和 `index-by`

```
(defn group-with [kf vf coll] ...)
;; 其中 kf 是 itm->k,vf 是 v->itm->v'

(def index-by #(group-with %1 (partial apply second) %2))

(def group-by #(group-with %1 (fnil conj []) %2))
```

`group-with`还将涵盖更广泛的使用场景,目前这些场景需要使用`reduce`。

编辑:对不起,我对Clojure还不熟悉,我打算把它当作答案发布。

2 个回答

0

选中
 
最佳答案

https://clojure.atlassian.net/browse/CLJ-2738创建了JIRA请求

我同意Sean在这里所说,我认为这与update-keys或update-vals,或同质值集无关。

也许这只是一种心理作用,update-vals和update-keys暗示了index-by的存在。不过,我很高兴在JIRA中看到这一点,谢谢!
一石二鸟,`index-by`可以通过这里提出的更通用的`group-by`来实现
https://ask.clojure.org/index.php/12319/can-group-by-be-generalized
0

您的key-by(into {} (map (juxt :id identity)) coll)(这内部使用了transducetransient/persistent!)。

这似乎与您打算使用的update-keysupdate-vals不相关(我们在一些地方使用了这两个,并且在其他地方也有与key-by等效的函数)。

是的,我也有使用`(into {} (map (juxt :id identity)) coll)`来实现这一目的。但1.11发布后,我发现可以使用`(update-vals first (group-by :id coll))`,并觉得这样做更简洁。

关于正交性,我认为我的问题并没有完全表达清楚。根据我的理解,`key-by`产生的是`update-vals`和`update-keys` supposed to operate 上的类型映射?我的问题是,是否疯狂到认为产生这种类型映射的`key-by`函数也属于核心集合,因为`update-vals`和`update-keys`都是在核心中。这三者全部放在核心中似乎是对称的:
update-valsupdate-keys可以在任何哈希表上操作——它们是通用的。
当然,但至少对于`update-vals`的预期使用场景看起来是同质类型映射。

https://clojure.atlassian.net/browse/CLJ-2651
"几乎总是需要应用update-vals映射的地图都有同质类型值。"

当然,这不是一个请求,只是一个问题,是否遗漏了一个将同质类型集合转换成同质类型的索引映射函数。:-)
...