Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap. If a pad collection is supplied, use its elements as necessary to complete last partition upto n items. In case there are not enough padding elements, return a partition with less than n items.
;; partition a list of 20 items into 5 (20/4) lists of 4 items (partition 4 (range 20)) ;;=> ((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15) (16 17 18 19)) ;; partition a list of 22 items into 5 (20/4) lists of 4 items ;; the last two items do not make a complete partition and are dropped. (partition 4 (range 22)) ;;=> ((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15) (16 17 18 19)) ;; uses the step to select the starting point for each partition (partition 4 6 (range 20)) ;;=> ((0 1 2 3) (6 7 8 9) (12 13 14 15)) ;; if the step is smaller than the partition size, items will be reused (partition 4 3 (range 20)) ;;=> ((0 1 2 3) (3 4 5 6) (6 7 8 9) (9 10 11 12) (12 13 14 15) (15 16 17 18)) ;; when there are not enough items to fill the last partition, a pad can be supplied. (partition 3 6 ["a"] (range 20)) ;;=> ((0 1 2) (6 7 8) (12 13 14) (18 19 "a")) ;; when a pad is supplied, the last partition may not be of the same size as the rest (partition 4 6 ["a"] (range 20)) ;;=> ((0 1 2 3) (6 7 8 9) (12 13 14 15) (18 19 "a")) ;; but only as many pad elements are used as necessary to fill the final partition. (partition 4 6 ["a" "b" "c" "d"] (range 20)) ;;=> ((0 1 2 3) (6 7 8 9) (12 13 14 15) (18 19 "a" "b"))
;; a step smaller than the partition-size results in reuse. (partition 3 1 [:a :b :c :d :e :f]) ;;=> ((:a :b :c) (:b :c :d) (:c :d :e) (:d :e :f))
;; When there are less than n items in the coll, partition's behaviour ;; depends on whether there is a pad or not ;; without pad (partition 10 [1 2 3 4]) ;;=> () ;; again, without pad (partition 10 10 [1 2 3 4]) ;;=> () ;; with a pad this time (note: the pad is an empty sequence) (partition 10 10 nil [1 2 3 4]) ;;=> ((1 2 3 4)) ;; or, explicit empty sequence instead of nil (partition 10 10 [] [1 2 3 4]) ;;=> ((1 2 3 4))
;; Partitioning 0 elements will produce an infinite seq of empty sequences (partition 0 [1 2 3]) ;; *hangs* (take 5 (partition 0 [1 2 3])) ;; => (() () () () ())
;; Using nil as a pad will let the incomplete partition in the result ;; Here we use it to drop every fourth element in an array (partition 3 4 nil [1 2 3 4 5 6 7 8 9]) ;;((1 2 3) (5 6 7) (9))
;; Here is a nice little trick to make a ring. (def foo [5 6 7 8]) (partition 2 1 foo foo) ;;=> ((5 6) (6 7) (7 8) (8 5)) ;; This will produce a part for each element of foo. ;; Without the pad stops sooner. (partition 2 1 foo) ;;=> ((5 6) (6 7) (7 8)) ;; Just how crazy can this get? (partition 4 1 foo foo) ;;=> ((5 6 7 8) (6 7 8 5)) ;; Not too crazy, this illustrates the ;; fact that the first use of the pad halts the partitioning. ;; To my way of thinking this is not what I expected. ;; The following alternative implementation continues ;; until the coll has been consumed once completely. (defn spiral ([n step coll] (spiral n step coll coll)) ([n step pad coll] (lazy-seq (when-let [s (seq coll)] (let [p (doall (take n s)) item (take n (apply concat p (repeat pad)))] (if (< 1 (count p)) (cons item (spiral n step pad (nthrest s step))) (list item))))))) (spiral 4 1 foo) ;;=> ((5 6 7 8) (6 7 8 5) (7 8 5 6) (8 5 6 7)) (spiral 4 2 foo) ;;=> ((5 6 7 8) (7 8 5 6)) (spiral 6 1 foo) ;;=> ((5 6 7 8 5 6) (6 7 8 5 6 7) (7 8 5 6 7 8) (8 5 6 7 8 5)) (def bar [:a :b :c]) (spiral 6 2 bar foo) ;;=> ((5 6 7 8 :a :b) (7 8 :a :b :c :a)) ;; Note that if you don’t need the padding, the function above can be ;; simplified a lot by using cycle: (defn spiral [n offset coll] (take (/ (count coll) offset) (partition n offset (cycle coll))))
;; In case you want behaviour similar to Ruby's each_slice, ;; where the last sequence doesn't necessarily have the same ;; size as the others, you can just provide an empty or nil pad value. (partition 3 3 nil (range 11)) ;;=> ((0 1 2) (3 4 5) (6 7 8) (9 10))) ;; This is the default behavior of partition-all (partition-all 3 3 (range 11)) ;;=> ((0 1 2) (3 4 5) (6 7 8) (9 10)))
;; There's no transducer arity for partition, but there is for partition-all ;; To enforce full partitions only, we can provide our own reducing function… (let [rf (completing (fn [acc x] (cond-> acc (= 3 (count x)) (conj x))))] (transduce (partition-all 3) rf [] '[a b c d e f g])) ;; => [[a b c] [d e f]] ;; Or we can add a take-while transducer… (into [] (comp (partition-all 3) (take-while #(= 3 (count %)))) '[a b c d e f g]) ;; => [[a b c] [d e f]]
Returns a lazy sequence of lists like partition, but may include partitions with fewer than n item...
Applies f to each value in coll, splitting it each time f returns a new value. Returns a lazy se...
Returns a lazy (infinite!) sequence of repetitions of the items in coll.
partition