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.