Welcome! Please see the About page for a little more info on how this works.

+11 votes
in Sequences by

At work we have some situations where we need to interleave lazy sequences in such a way that if one sequence is shorter than the other we want elements from the longer sequence to be concatenated after the interleaving runs out of the shorter sequence(s).

The following code could be used -- a slight variant of the existing interleave function:

(defn interleave-all
  "Like interleave, but stops when the longest seq is done, instead of
   the shortest."
  {:copyright "Rich Hickey, since this is a modified version of interleave"}
  ([] ())
  ([c1] (lazy-seq c1))
  ([c1 c2]
    (let [s1 (seq c1) s2 (seq c2)]
       (and s1 s2) ; there are elements left in both
       (cons (first s1) (cons (first s2)
                              (interleave-all (rest s1) (rest s2))))
       s1 ; s2 is done
       s2 ; s1 is done
  ([c1 c2 & colls]
    (let [ss (filter identity (map seq (conj colls c2 c1)))]
      (concat (map first ss) (apply interleave-all (map rest ss)))))))

1 Answer

+2 votes
selected by