faoxis
faoxis

Reputation: 2022

How to converter list of tuples to tuple of lists?

I have the example to show what I mean:

fun makeRange(i: Int) = Pair(i - 1, i + 1)
val listOfData = listOf(1, 2, 3, 4, 5, 6)

val pairs = listOfData
                .map { makeRange(it) }
val leftRange = pairs.map { it.first }
val rightRange = pairs.map { it.second }

I have some list and function which returns a tuple. But the result I need is touple of two lists. I need something like that:

    // can I get something like that ?
    val (leftRange, rightRange) = listOfData.map { makeRange(it) } ...

Is there a way to do it?

Upvotes: 1

Views: 762

Answers (2)

Ori
Ori

Reputation: 13

Seems like kotlin unzip function is just what you're looking for. https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/unzip.html

In your example the usage would look something like

val (leftRange, rightRange) = pairs.unzip()

Upvotes: 1

Roland
Roland

Reputation: 23312

If you really want to destructure it like this, I would also split up your makeRange-function, e.g.:

fun makeLeftRange(i: Int) = i - 1
fun makeRightRange(i: Int) = i + 1
fun makeRange(i: Int) = makeLeftRange(i) to makeRightRange(i) // if you still need it...

Then you can destructure as follows:

val (leftRange, rightRange) = listOfData.map(::makeLeftRange) to listOfData.map(::makeRightRange)

Or if it is really just such an easy function, why not just use the following instead:

val (leftRange, rightRange) = listOfData.map(Int::dec) to listOfData.map(Int::inc)
// or
val (leftRange, rightRange) = listOfData.map { it - 1 } to listOfData.map { it + 1 }

If you want to keep your makeRange as is and want to do it that way, it will get a bit uglier, e.g.:

val (leftRange, rightRange) = listOfData.map(::makeRange).let { 
  listOfPairs -> listOfPairs.map { it.first } to listOfPairs.map { it.second }
}

Basically reusing what you've shown in an additional let-statement.

Upvotes: 1

Related Questions