Reputation: 1351
I have given a list of integers. I need to map always two following elements in further progressing. If the input list contains a invalid count of elements the last ones should be dropped. Here is an example:
[1, 2, 3, 4, 5, 6, 7] //Input
[(1, 2), (3, 4), (5, 6)] //Output
I wrote to functions to get the wanted output but I think they are both inefficient.
First i tried it with a functional approach. But it needs two filter calls and a zip call for the resulting list. So it iterates 2.5 times over the entier list.
Two imrpove this I tried a iterative approach. It only iterates once over the list and is possibly the fastest version. But it uses multiple mutable variables/lists. Also it is not as easy to understand as the functinal approach. (And it breaks the cleaness of the rest of the code)
fun main(args: Array<String>) {
mapFunctional()
mapIterative()
}
fun mapFunctional() {
val list: List<Int> = listOf(1, 2, 3, 4, 5, 6, 7)
val output: List<Pair<Int, Int>> = list.filterIndexed { index, _ ->
index % 2 == 0
}.zip(list.filterIndexed {
index, _ -> index % 2 == 1
})
println(output)
}
fun mapIterative() {
val list: List<Int> = listOf(1, 2, 3, 4, 5, 6, 7)
val output: MutableList<Pair<Int, Int>> = mutableListOf()
var index = 0
while (index < list.size - 1) {
output.add(list[index++] to list[index++])
}
println(output)
}
Is their a good (efficient) way to achieve this in a functinal aprroach or is it only possible with a classic loop?
Upvotes: 5
Views: 7526
Reputation: 31710
If you want a List<Pair>
, you can use a standard library call for this called windowed
.
val myList = listOf(1, 2, 3, 4, 5, 6, 7)
val listOfPairs = myList.windowed(2, 2).map { Pair(it[0], it[1]) }
// [(1, 2), (3, 4), (5, 6)]
The windowed
function will return a List<List<Int>>
, so you'll have to map the internal List<Int>
to a Pair<Int, Int>
. The windowed
function by default will drop partial windows.
Upvotes: 6
Reputation: 148119
You can use the standard library function .chunked(n)
for this purpose:
val list = listOf(1, 2, 3, 4, 5, 6, 7)
val output = list.chunked(2).dropLastWhile { it.size < 2 }
As chunked
preserves the last partial list containing less items than the required size, you need to handle this and drop it conditionally with .dropLastWhile { ... }
Upvotes: 4