/ KOTLIN, STDLIB, STACK OVERFLOW

Elements combination in Kotlin collections

I’m not a regular StackOverflow user, neither as a contributor, nor to ask questions. However, I recently stumbled upon a question, tried to help…​ and failed. I was pointed out my answer was wrong - thanks for everyone who did. I think failures are great occasions to learn something new!

In this post, I’d like to detail what I learned after digging further: there are several ways to combine elements from an existing collection in Kotlin stdlib.

Combining with next

The fist combining function is to associate one element with the next, in pairs.

The signature is:

fun <T> Iterable<T>.zipWithNext(): List<Pair<T, T>>

Here’s a simple example on how to use it:

val elements = listOf("A", "B", "C", "D", "E", "F", "G", "H")

elements.zipWithNext().forEach {
    print(it)
}

It will output:

(A, B)(B, C)(C, D)(D, E)(E, F)(F, G)(G, H)

Another flavor of zipWithNext is:

fun <T, R> Iterable<T>.zipWithNext(
    transform: (a: T, b: T) -> R
): List<R>

This allows to run a transformation function on the pairs, e.g.:

elements.zipWithNext { first, second ->
        "$first$second "
    }.forEach {
        print(it)
    }

The corresponding output is:

AB BC CD DE EF FG GE

Combining using chunks

The second combining function is to combine elements in chunks of a specific size:

fun <T> Iterable<T>.chunked(size: Int): List<List<T>>

Here’s how to use it:

elements.chunked(2).forEach {
        print(it)
    }

It yields the following:

[A, B][C, D][E, F][G, H]

As for the previous function, there’s an alternative flavor using a transform function:

fun <T, R> Iterable<T>.chunked(
    size: Int,
    transform: (List<T>) -> R
): List<R>

Using it is quite straightforward:

elements.chunked(3) {
        print("${it.joinToString("")} ")
    }

The result is:

ABC DEF GH
The size of the last chunk may not be the same as the regular chunk size. That is the case if the remainder of the division of the collection’s size by the chunk’s size is not 0.

Combining using sliding window

The final combining function uses a sliding window over the elements in the collection. Parameters include the window "width" and the sliding "step":

fun <T> Iterable<T>.windowed(
    size: Int,
    step: Int = 1,
    partialWindows: Boolean = false
): List<List<T>>

It’s a generalization of the first two functions:

  1. zipWithNext == windowed(2, 1)

    There’s a slight difference, as zipWithNext() returns Pair, while windowed() returns List

    The exact equivalence should be:

    zipWithNext().map { listOf(it.first, it.second) } = windowed(2, 1)

  2. chunked(x) == windowed(x, x, true)

As the 2 previous functions, windowed also offers a transform flavor.

Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with narrower interests like Software Quality, Build Processes and Rich Internet Applications. Currently working for Exoscale. Also double as a teacher in universities and higher education schools, a trainer and triples as a book author.

Read More