pixix4
pixix4

Reputation: 1351

Map list to tuples of following elements

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

Answers (2)

Todd
Todd

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

hotkey
hotkey

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

Related Questions