【问题标题】:Why exactly is filtering a set more performant than filtering a vector?为什么过滤集合比过滤向量更高效?
【发布时间】:2022-11-23 00:34:49
【问题描述】:

经过一些研究,我最近能够通过使用集合而不是向量来比较来显着提高某些代码的性能。这是初始代码的一个简单示例:

(def target-ids ["a" "b" "c"])

(def maps-to-search-through 
  [{"id": "a" "value": "example"} 
   {"id": "e" "value": "example-2"}])

(filter (fn [i] (some #(= (:id i) %) target-ids)) maps-to-search-through)

这是优化后的代码:

(def target-ids #{"a" "b" "c"})

(def maps-to-search-through
  [{"id": "a" "value": "example"} 
   {"id": "e" "value": "example-2"}])

(filter (comp target-ids :id) maps-to-search-through)

作为参考,target-idsmaps-to-search-through 都是动态生成的,每个都可以包含数千个值——尽管 maps-to-search-through 总是至少比 target-ids 大 5 倍。

我在网上找到的所有建议和文档都表明这种改进,特别是使用集合而不是向量,会明显更快,但没有详细说明为什么会这样。我知道在最初的情况下,filter 做了很多工作——在每一步迭代两个向量。但我不明白那是怎么回事不是改进代码中的案例。

谁能帮忙解释一下?

【问题讨论】:

    标签: vector filter clojure set lisp


    【解决方案1】:

    集合是设计为仅包含唯一值的数据结构。您还可以将它们用作函数来检查给定值是否是集合的成员 - 就​​像您使用 target-ids 集合一样。它基本上归结为在 JVM 端调用 Set.contains,它使用了一些聪明的基于哈希的逻辑。

    您的第一个解决方案使用 some 循环遍历向量,因此它类似于嵌套的 for 循环,后者显然更慢。

    【讨论】:

      猜你喜欢
      • 2013-12-30
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-24
      • 2021-08-13
      • 1970-01-01
      相关资源
      最近更新 更多