好事是这里有个搜索功能。我最近遇到了类似的情况,我想对不同输入集合并在一起进行处理,最后得到一个集合,所以我试了几个不同的方法。
下面是这个例子中的REPL会话。我使用了criterium进行了一段时间的性能测试后,得出结论:通过多个`into`来穿引集合的方法可能是最地道的,而且其性能并不比`catreduce`差。
(def input1 (into [] (range 100000)))
(def input2 (into [] (range 999 9999)))
(def xf1 (filter odd?))
(def xf2 (map inc))
(def xf3 (take 100))
(def xf4 (comp (filter even?) (map dec) (take 1000)))
;; concat (不喜欢它懒惰和分配了多个中间集合)
(def result (into []
(concat
(into [] xf1 input1)
(into [] xf2 input1)
(into [] xf3 input2)
(into [] xf4 input2))))
;; cat (仍然分配中间集合)
(= result
(into []
cat
[(into [] xf1 input1)
(into [] xf2 input1)
(into [] xf3 input2)
(into [] xf4 input2)]))
;; intos (没有分配中间资源,但有多次瞬态/持久切换)
;; - 但这应该不是太大问题,因为它们的复杂度都是O(1)
(= result
(-> []
(into xf1 input1)
(into xf2 input1)
(into xf3 input2)
(into xf4 input2)))
;; reduce into
;; - 几乎与intos解决方案相同,无需多次调用into
(= result
(reduce
#(into %1 (second %2) (first %2))
[]
[[input1 xf1]
[input1 xf2]
[input2 xf3]
[input2 xf4]]))
;; catreduce
;; - 尝试查看是否可以不进行许多瞬态/持久切换就完成它
(defn catduce
"借鉴自clojure.core/cat"
[rf]
(fn
([] (rf))
([result] (rf result))
([result input+xf]
(transduce (second input+xf) rf result (first input+xf)))))
(= result
(into [] catduce
[[input1 xf1]
[input1 xf2]
[input2 xf3]
[input2 xf4]]))