Skip to content

Commit 3399e9b

Browse files
authored
Merge pull request #98 from tomdl89/window
Add window function
2 parents 7c36bc6 + 8ed4ad5 commit 3399e9b

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/medley/core.cljc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,35 @@
506506
([pred coll]
507507
(partition-between (fn [_ x] (pred x)) coll)))
508508

509+
(defn window
510+
"A sliding window, returning a lazy sequence of partitions, containing each
511+
element and n-1 preceeding elements, when present. Therefore partitions at the
512+
start may contain fewer items than the rest. Returns a stateful transducer
513+
when no collection is provided. For a sliding window containing each element
514+
and n-1 _following_ elements, use `clojure.core/partition` with a `step` size
515+
of 1."
516+
{:added "1.9.0"}
517+
([n]
518+
(fn [rf]
519+
(let [part #?(:clj (java.util.ArrayList. n) :cljs (array))]
520+
(fn
521+
([] (rf))
522+
([result] (rf result))
523+
([result x]
524+
#?(:clj (.add part x) :cljs (.push part x))
525+
(when (< n #?(:clj (.size part) :cljs (.-length part)))
526+
#?(:clj (.remove part 0) :cljs (.shift part)))
527+
(rf result (vec #?(:clj (.toArray part) :cljs (.slice part)))))))))
528+
([n coll]
529+
(letfn [(part [part-n coll]
530+
(let [run (doall (take part-n coll))]
531+
(lazy-seq
532+
(when (== part-n (count run))
533+
(cons run
534+
(part (min n (inc part-n))
535+
(if (== n part-n) (rest coll) coll)))))))]
536+
(part (min 1 n) coll))))
537+
509538
(defn indexed
510539
"Returns an ordered, lazy sequence of vectors `[index item]`, where item is a
511540
value in coll, and index its position starting from zero. Returns a stateful

test/medley/core_test.cljc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,28 @@
398398
[1 2 3 2 8 9])
399399
[[1] [2] [3 2] [8]]))))
400400

401+
(deftest test-window
402+
(testing "sequences"
403+
(is (= (m/window 2 nil) '()))
404+
(is (= (m/window 2 [:a]) '((:a))))
405+
(is (= (m/window 2 [:a :b]) '((:a) (:a :b))))
406+
(is (= (m/window 2 [:a :b :c]) '((:a) (:a :b) (:b :c))))
407+
(is (= (take 3 (m/window 0 [:a :b :c])) '(() () ())))
408+
(is (= (m/window 10 [:a :b :c]) '((:a) (:a :b) (:a :b :c)))))
409+
(testing "transducers"
410+
(is (= (transduce (m/window 2) conj nil) []))
411+
(is (= (transduce (m/window 2) conj [:a]) [[:a]]))
412+
(is (= (transduce (m/window 2) conj [:a :b]) [[:a] [:a :b]]))
413+
(is (= (transduce (m/window 2) conj [:a :b :c]) [[:a] [:a :b] [:b :c]]))
414+
(is (= (transduce (m/window 0) conj [:a :b :c]) [[] [] []]))
415+
(is (= (transduce (m/window 10) conj [:a :b :c]) [[:a] [:a :b] [:a :b :c]]))
416+
(is (= (transduce (m/window 2)
417+
(completing (fn [coll x]
418+
(cond-> (conj coll x) (= [:a :b] x) reduced)))
419+
[]
420+
[:a :b :c :d])
421+
[[:a] [:a :b]]))))
422+
401423
(deftest test-indexed
402424
(testing "sequences"
403425
(is (= (m/indexed [:a :b :c :d])

0 commit comments

Comments
 (0)