Sliding Windows in Clojure

I was doing a little Clojure programming and my son asked me if the computer could
make it go 1 2 3, 2 3 4, 3 4 5, …
I thought, hmm, that’s a sliding window.
Here was my first thought:
(->> (range 1 4)
(map (fn [x] [x (inc x) (inc (inc x))])))
;;=> ([1 2 3] [2 3 4] [3 4 5])
I asked if he wanted it as just one list. He asked me to show him, so I thought… I’m mapping over this and need to concatenate the lists. Wait, that’s literally mapcat:
(->> (range 1 4)
(mapcat (fn [x] [x (inc x) (inc (inc x))])))
;;=> (1 2 3 2 3 4 3 4 5)
He said he preferred the little lists to the one big one. Good thinking.
Then I thought, can we make it shorter? I could use iterate instead of the vector literal:
(->> (range 1 4)
(map #(take 3 (iterate inc %))))
;;=> ((1 2 3) (2 3 4) (3 4 5))
Looking at this, it’s really easy to parameterize:
(let [window-size 3
number-of-windows 3]
(->> (range 1 (inc number-of-windows))
(map #(take window-size (iterate inc %)))))
;;=> ((1 2 3) (2 3 4) (3 4 5))
Then I thought, the first number in a little collection forms the basis for the next little collection. I also like this way best because it starts with a literal vector [1 2 3]:
(->> [1 2 3]
(iterate #(map inc %))
(take 3))
;;=> ([1 2 3] (2 3 4) (3 4 5))
It can be parameterized as well:
(let [number-of-windows 3]
(->> [1 2 3]
(iterate #(map inc %))
(take number-of-windows)))
;;=> ([1 2 3] (2 3 4) (3 4 5))
After doing all that, I realize that this isn’t a sliding window at all! In a true sliding window problem, you don’t know what the elements will be. THIS is a sliding window:
(let [window-size 3
step-size 1]
(partition window-size step-size (range 1 (inc 5))))
;;=> ((1 2 3) (2 3 4) (3 4 5))
In any case, Clojure is awesome for this type of work.




