clojure - 过滤,然后映射?或者只使用一个for循环?

标签 clojure

我不断遇到这样的情况:我需要通过某种函数过滤一组 map ,然后从每个结果 map 中提取一个值以形成最终的集合。

我经常使用这个基本结构:

(map :key (filter some-predicate coll))

我发现这基本上完成了与 for 循环相同的事情:

(for [x coll :when (some-predicate x)] (:key x))

一种方法比另一种方法更有效吗?我认为 for 版本会更有效,因为我们只遍历集合一次。这准确吗?

最佳答案

两者都没有显着差异。

这两者都返回一个未实现的惰性序列,每次读取一个项目时都会计算它。第一个不会遍历列表两次,而是创建一个惰性序列,该序列生成与过滤器匹配的项目,然后立即由映射函数使用(仍然是惰性的)。因此,在第一种情况下,您有一个惰性序列惰性地消耗另一个惰性序列中的项目。另一方面,对 for 的调用会生成一个在每个步骤中包含大量逻辑的惰性序列。

您可以看到示例扩展为的代码:

(pprint (macroexpand-1 '(for [x coll :when (some-predicate x)] (:key x)))) 

总体而言,性能与第二种方法非常相似,可能产生的垃圾稍微少一些,因此您根据性能在这些方法之间做出决定的唯一方法是基准测试。根据风格,我选择第一个,因为它更短,但如果有更多阶段,我可能会选择使用 thread-last 宏来编写它。

(->> coll
     (filter some-predicate)
     (take some-limit)
     (map :key))

虽然这基本上取决于个人风格

关于clojure - 过滤,然后映射?或者只使用一个for循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29223193/

相关文章:

programming-languages - 哪些因素可以决定 Clojure、Scala 或 Haskell 是否会获得关注?

algorithm - 如何在 Clojure 中将序列划分为递增的子序列?

clojure - 历史上的数据查询

vector - Clojure 引用向量

java - 如何调用StaticMethodExpr.eval?

ruby-on-rails - Rails 类型的 webapp 中的 'Model' 如何用函数式编程语言实现?

clojure - clojure 中的分析(适用于大型代码)

clojure - 这个 ClojureScript REPL 的生命周期是多少?

multithreading - 你如何杀死一个 core.async/thread?

clojure - 如何在 Clojure 中添加这个哈希表?