Clojure查找性能向量vs集

时间:2011-10-03 08:37:18

标签: clojure

我有一小部分小于50的分类物品我经常检查特定物品是否在集合中,

此,

(time
 (let [a [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]]
   (dotimes [i 100000]
     (filter (fn [[k]] (= k 15)) a))))
如果我使用一套,

需要10毫秒,

(time
 (let [a (sorted-set 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)]
   (dotimes [i 100000]
   (a 15))))

它总是需要至少两倍。我不明白的是,set应该针对查找进行优化,为什么过滤更快?

2 个答案:

答案 0 :(得分:11)

过滤器是懒惰的。因为你没有评估(filter (fn [[k]] (= k 15)) a)的结果,所以除了做一个懒惰的序列之外它什么也没做。

事实上,(fn [[k]] (= k 15))甚至不正确但你没有看到,因为它没有被评估。

(let [a [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]]
     (filter (fn [[k]] (= k 15)) a))
=> java.lang.UnsupportedOperationException: nth not supported on this type: Integer
    [Thrown class java.lang.RuntimeException]

你想要像

这样的东西
(time
 (let [a [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]]
   (dotimes [i 100000]
     (some (fn [k] (= k 15)) a))))

"Elapsed time: 173.689 msecs"
nil

而不是错误的:

(time
 (let [a [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]]
   (dotimes [i 100000]
     (filter (fn [[k]] (= k 15)) a))))

"Elapsed time: 33.852 msecs"
nil

答案 1 :(得分:3)

filter是一个懒惰的函数。尝试添加first以强制评估filter函数生成的延迟序列。你的匿名函数也有一个小错误:

(time
 (let [a [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]]
   (dotimes [i 100000]
     (first (filter (fn [k] (= k 15)) a)))))

"Elapsed time: 126.659769 msecs"

排序集:

(time
 (let [a (sorted-set 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)]
   (dotimes [i 100000]
   (a 15))))
"Elapsed time: 19.467465 msecs"

希望有所作为。