Lazily partition a sequence into differently-sized chunks in Clojure

Viewed 142

How to lazily partition a sequence into differently-sized chunks in Clojure? Sort of like (partition n xs), but for a sequence of ns. For example:

(chunker [3 4 5] (range 12))
=> ((0 1 2) (3 4 5 6) (7 8 9 10 11))
1 Answers

I needed this to chunk some inputs and didn't want to use Instaparse. Here is a lazy solution that supports cycled chunk sizes:

(defn chunker
  "Like (partition N input) but for a sequence of Ns."
  [[chunk & chunks] coll]
  (lazy-seq
    (when-let [s (seq coll)]
      (cons (take chunk s)
        (when chunks (chunker chunks (drop chunk s)))))))

Usage

(chunker [3 4 5] (range 20))
=> ((0 1 2) (3 4 5 6) (7 8 9 10 11)) ;; note not input not fully consumed.

(chunker (cycle [3 4 5]) (range 20))
=> ((0 1 2) (3 4 5 6) (7 8 9 10 11) (12 13 14) (15 16 17 18) (19))
Related