generics - 映射集合而不将它们转换为列表

标签 generics collections clojure

是否可以在不将集合转换为列表的情况下映射集合?我知道向量的 mapv,但是集合或映射呢?是否有一个通用的 map 函数将每个集合视为仿函数(即可映射的东西)并在映射后保留其类型?

这是我的想法和现在发生的事情:

(map inc [1 2 3])         ; => [2 3 4], instead I get: (2 3 4)
(map inc #{1 2 3})        ; => #{3 2 4}, instead I get: (3 2 4)
(map inc {:a 1 :b 2 :c 3} ; => {:a 2 :b 3 :c 4}, instead I get: ClassCastException

最佳答案

函数的返回值并未准确列出,这只是它们在打印时在 REPL 中的表示方式。它们实际上是 clojure.lang.LazySeq 的实例,正如您在此处看到的:

(class (map inc [1 2 3]))
=> clojure.lang.LazySeq

Clojure 尝试将所有集合视为可排序,而不是可映射。 Seq 抽象允许将许多转换组合成集合上的操作管道,其中维护原始输入类型通常没有意义,特别是在性能(速度)方面。在这种情况下,Clojure 的动态特性实际上非常有用。

将操作的输出转换为您想要的集合类型很简单:

(-> (map inc [1 2 3])
    (vec))

或者更简单地说,使用into:

(into [] (map inc [1 2 3]))

into 可用于列表、 map 和集合:

(into #{} (map inc #{1 2 3}))
=> #{4 3 2}

在您尝试映射 Hashmap 的示例中,map 会以 clojure.lang.MapEntry 的形式传递一系列键值对,所以 inc 需要一个数字,无法直接处理它。

您可以执行类似的操作,使用解构来提取键和值:

(into {} (for [[k v] {:a 1 :b 2 :c 3}]
           [k (inc v)]))

关于generics - 映射集合而不将它们转换为列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44095544/

相关文章:

swift - 返回两个泛型之一的函数

clojure - 基座提前终止不起作用

clojure - Clojure 被认为是 Lispy 还是 Schemey?

clojure - 如何在 Clojure 的 fn 中使用 undefined symbol ?

java - 泛型扩展

generics - Kotlin - "where"通用约束问题

c# - 如何将验证属性应用于集合中的对象?

java - Collection.toArray(IntFunction<T[]> generator) 不接收集合大小

javascript - Backbone.Collection 触发 'reset' 但不是 'add'

c# - 将openCV的vector<Point2f>转换为C#的Collections::Generic::List<Windows::Point>