0

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.

New Dev
  • 48,427
  • 12
  • 87
  • 129
Fabrizio
  • 89
  • 1
  • 1
  • 8
  • 1
    Some other solutions here: https://stackoverflow.com/questions/53749357/idiomatic-way-to-create-n-ary-cartesian-product-combinations-of-several-sets-of – Tenfour04 Nov 11 '20 at 16:43
  • What should it do if the list contains any duplicates (e.g. ā€˜a, b, b, c’)? – gidds Nov 11 '20 at 21:10

2 Answers2

1

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)]
}
Aplet123
  • 33,825
  • 1
  • 29
  • 55
0

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

cactustictacs
  • 17,935
  • 2
  • 14
  • 25