Fabrizio
Fabrizio

Reputation: 89

Kotlin: combine all elements in list in a functional way

I'm new to Kotlin and would like to combine all elements of a list.

I tried zipWithNext, but it combines an element only with the next one.

   val letters = ('a'..'f').toList()
   val pairs = letters.zipWithNext()
    
   println(letters) // [a, b, c, d, e, f]
   println(pairs) // [(a, b), (b, c), (c, d), (d, e), (e, f)]

I'd like something like this:

From this [a, b, c, d] to this [(a, b), (a, c), (a, d), (b, a), (b, c), (b, d), (c, a), (c, b), (c, d), (d, a), (d, b), (d, c)]

It can be done in imperative way, but I was wonder how to do it in a functional way.

Upvotes: 0

Views: 881

Answers (2)

cactustictacs
cactustictacs

Reputation: 19524

If you're ok with not doing it all in one pipeline (and honestly I'd encourage people to break things down into smaller, well-named functions more often!) you can do something like

val letters = ('a'..'f').toList()
fun allPairs(c: Char) = letters.map { Pair(c, it) }
val combos = letters.flatMap(::allPairs)
print(combos)

or

fun allPairs(c: Char) = letters.filterNot { it == c }.map { Pair(c, it) }

if you don't want duplicates

Upvotes: 1

Aplet123
Aplet123

Reputation: 35482

You can use flatMap and withIndex to take the cartesian product with every element other than itself:

fun main() {
    val letters = ('a'..'d').toList()
    val pairs = letters.withIndex().flatMap { (i1, e1) ->
        letters.withIndex().filter { (i2, e2) ->
            i1 != i2
        }.map { (i2, e2) ->
            Pair(e1, e2)
        }
    }

    println(letters) // [a, b, c, d]
    println(pairs) // [(a, b), (a, c), (a, d), (b, a), (b, c), (b, d), (c, a), (c, b), (c, d), (d, a), (d, b), (d, c)]
}

Upvotes: 1

Related Questions