是否可以在不将集合转换为列表的情况下映射
集合?我知道向量的 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/