Good thing there's a search function around here. I recently ran into similar situations where I wanted to perform different transformations on a couple of input collections and end up with one collection, so I tried out a few different approaches.
Here's my REPL session for that. After some basic perf testing with criterium, I concluded that the solution threading a collection through multiple `into`-s is probably the most idiomatic and it isn't worse wrt performance than the `catduce` one.
(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 (don not like that it is lazy and there are several intermediate colls allocated)
(def result (into []
(concat
(into [] xf1 input1)
(into [] xf2 input1)
(into [] xf3 input2)
(into [] xf4 input2))))
;; cat (still allocates intermediate collections)
(= result
(into []
cat
[(into [] xf1 input1)
(into [] xf2 input1)
(into [] xf3 input2)
(into [] xf4 input2)]))
;; intos (no intermediate allocations, but multiple transient/persistent switches)
;; - this should not be too much of a problem though as they both are O(1)
(= result
(-> []
(into xf1 input1)
(into xf2 input1)
(into xf3 input2)
(into xf4 input2)))
;; reduce into
;; - almost the same as the intos solution, without having to write into multiple times
(= result
(reduce
#(into %1 (second %2) (first %2))
[]
[[input1 xf1]
[input1 xf2]
[input2 xf3]
[input2 xf4]]))
;; catduce
;; - tried to see if it can be done without the many transient/persistent switches
(defn catduce
"adopted from 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]]))