August 25, 2018
Just Juxt #11: Partition a Sequence (4clojure #54)
Write a function which returns a sequence of lists of x items each. Lists of less than x items should not be returned.
(ns live.test
(:require [cljs.test :refer-macros [deftest is testing run-tests]]))
(defn partition-seq [n s]
)
(deftest partition-seq-test
(is (= (partition-seq 3 (range 9)) '((0 1 2) (3 4 5) (6 7 8))))
(is (= (partition-seq 2 (range 8)) '((0 1) (2 3) (4 5) (6 7))))
(is (= (partition-seq 3 (range 8)) '((0 1 2) (3 4 5)))))
(run-tests)
This problem is holding up a big sign that says:
"Hey! The
partition
function is totally awesome, you should check out how it works!"
So here's how it works:
user=> (source partition)
(defn partition
"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."
{:added "1.0"
:static true}
([n coll]
(partition n n coll))
([n step coll]
(lazy-seq
(when-let [s (seq coll)]
(let [p (doall (take n s))]
(when (= n (count p))
(cons p (partition n step (nthrest s step))))))))
([n step pad coll]
(lazy-seq
(when-let [s (seq coll)]
(let [p (doall (take n s))]
(if (= n (count p))
(cons p (partition n step pad (nthrest s step)))
(list (take n (concat p pad)))))))))
Learning from these concepts, we could create a solution like this:
(defn partition-seq [n coll]
(loop [c coll partitioned []]
(if (< (count c) n)
partitioned
(recur (drop n c) (conj partitioned (take n c))))))
(run-tests)
But here's a way to do it with juxt
:
(defn partition-seq [n coll]
(let [[a b] ((juxt take drop) n coll)]
(if (= (count a) n)
(cons a (partition-seq n b)))))
(run-tests)
Inside our let binding is a destructuring form, which pulls apart the items (plugging in the first test case) and creates local bindings for them named a
and b
:
((juxt take drop) 3 (range 9))