这里有一个搜索功能真是太好了。我最近遇到了类似的情况,我希望对几个输入集合执行不同的转换并最终获得一个集合,所以我尝试了几种不同的方法。
以下是我的REPL会话。在对criterium进行了一些基本的性能测试后,我得出结论,通过多个 `into` 线程集合的解决方案可能是最符合常规使用的,并且在性能上并不比 `catduce` 差。
(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
xf1 input1)
xf2 input1)
xf3 input2)
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]]))
;; catduce
;; - 尝试在不进行多次瞬时/持久转换的情况下完成
(defn catduce
"借鉴自 clojure.core/cat"
[rf]
(fn
[] []
[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]]))