Is there a collection function like map to turn every item in a list into two items?

Viewed 115

Say I have a list of integers, as such:

val list = listOf(1, 2, 3, 5, 8, 13)

I want to run an operation to create a similar list but with an additional element after every element. For example, we should be able to add a -99 after each element as such:

[1, -99, 2, -99, 3, -99, 5, -99, 8, -99, 13, -99]

I can do this with a forEach loop and temporary list easily, as such:

val list = listOf(1, 2, 3, 5, 8, 13)
val tempList = mutableListOf<Int>()
list.forEach {
    tempList.add(it)
    tempList.add(-99)
}
println(tempList) // [1, -99, 2, -99, 3, -99, 5, -99, 8, -99, 13, -99]

But this seems unnecessarily verbose and imperative. Another way I found is to map each item to a list with the two elements, creating a list of lists, and flattening the result. Example:

val list = listOf(1, 2, 3, 5, 8, 13)
val mapFlatten = list
    .map { listOf(it, -99) }
    .flatten()
 
println(mapFlatten) // [1, -99, 2, -99, 3, -99, 5, -99, 8, -99, 13, -99]

However, creating a list of lists and then flattening seems unnecessarily redundant. Is there any list operation that allows us to do this in a simpler way?

1 Answers

You could simplify your second option by using flatMap directly:

val list = listOf(1, 2, 3, 5, 8, 13)
val mapFlatten = list.flatMap { listOf(it, -99) }

You still have these intermediate lists technically, but I'm not sure it can be simplified further.

If you really have huge lists and you're concerned about extra allocations, you could fallback to just building a list manually like you did, unless you're not scared of experimental functions and are ok with buildList:

val list = listOf(1, 2, 3, 5, 8, 13)
val mapFlatten = buildList(2 * list.size) {
    list.forEach {
        add(it)
        add(-99)
    }
}
Related