我有一小部分小于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应该针对查找进行优化,为什么过滤更快?
答案 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"
希望有所作为。