Search

Dark theme | Light theme

December 9, 2022

Kotlin Kandy: Transforming Collection Items With Index

If we want to transform items in a collection we can use the map method. If we also want to use the index of the element in the collection in the transformation we must use the mapIndexed method. We must provide a lambda function with 2 arguments, where the first argument is the index of the element in the collection and the second argument is the element in the collection.

In the following examples we use the mapIndexed and the related mapIndexedNotNull and mapIndexedTo methods:

// With mapIndexed we can use a lambda with 2 arguments:
// the first argument is the index,
// the second argument is the value.
assert(listOf(3, 20, 10, 2, 1).mapIndexed { index, n -> n * index } ==
        listOf(0, 20, 20, 6, 4))

// Instead of using the indices property we can use
// mapIndexed to get all the indices.
assert(listOf(3, 20, 10, 2, 1).mapIndexed { index, _ -> index } ==
        listOf(0, 1, 2, 3, 4))
assert(listOf(3, 20, 10, 2, 1).indices == 0..4)

// mapIndexed also works on ranges.
val lettersIndex = ('a'..'z').mapIndexed { index, letter -> letter to (index + 1) }
assert(lettersIndex.take(3) == listOf('a' to 1, 'b' to 2, 'c' to 3))

// Using toMap we get a nice lookup map to find the position
// of a letter in the alphabet.
assert("kotlin".map { c -> lettersIndex.toMap().get(c) } == listOf(11, 15, 20, 12, 9, 14))


// The mapIndexedNotNull method only returns non-null results.
val others = listOf("Kotlin", "Groovy", "Java", "Clojure")
    .mapIndexedNotNull { index, language -> if (index == 2) null else language }
assert(others == listOf("Kotlin", "Groovy", "Clojure"))


// With mapIndexTo we can add the output of the
// transform lambda function to an existing
// mutable collection.
val storage = mutableListOf(90, 10, 3)
assert(listOf(7, 42, 100)
        .mapIndexedTo(storage) { index, n -> index * n } ==
            listOf(90, 10, 3, 0, 42, 200))

Written with Kotlin 1.7.20.