Collection processing in Kotlin: Windowing, zipping and chunking
This is a chapter from the book Functional Kotlin. You can find it on LeanPub or Amazon. It is also available as a course.
zip
is used to connect two collections into one in a way that forms pairs of elements that are in the same positions. So, zip
between List<T1>
and List<T2>
returns List<Pair<T1, T2>>
. The result list ends when the shortest zipped collection ends.
The
zip
function reminds me of polonaise - a traditional Polish dance. One feature of this dance is that a line of pairs is separated down the middle, then these pairs reform when they meet again.
We can reverse zip
operation using unzip
, that transform a list of pairs into a pair of lists.
When we need to connect adjacent elements of a collection into pairs, there is zipWithNext
.
There is also a variant of zipWithNext
, that produces a list of results from a transformation, instead of a list of pairs.
Windowing
To connect adjacent elements into collections, the universal method is windowed
, which returns a list of sublists of our list, where each is the next window of a given size. These sublists are made by sliding along this collection with the given step
. In simpler words, you might imagine that windowed
has a trolley of size size
that makes a snapshot (a copy) of the elements below it and then makes a step of size step
. When the end of the trolley falls off the collection, the process ends. However, suppose partialWindows
is set to true
. In that case, our trolley needs to fully fall off the collection for the process to stop (with partialWindows
for the process to stop, our trolley can extend past the end of the collection to include any remaining elements).
The windowed
method is really universal but also complicated. So, one function that builds on it is chunked
.
chunked
divides our collection into chunks that are sub-collections of a certain size. It does not lose elements, so the last chunk might be smaller than the argument value.