Given I have two lists:
val ints = listOf(0, 1, 2)
val strings = listOf("a", "b", "c")
and I want all possible combinations of their elements
0a, 1a, 2a, 0b
etc
is there a more elegant way than:
ints.forEach { int ->
strings.forEach { string ->
println("$int $string")
}
}
So we say that there are 5 factorial = 5! = 5x4x3x2x1 = 120 ways to arrange five objects.
You could write these extension functions based on flatMap
stdlib function:
// Extensions
fun <T, S> Collection<T>.cartesianProduct(other: Iterable<S>): List<Pair<T, S>> {
return cartesianProduct(other, { first, second -> first to second })
}
fun <T, S, V> Collection<T>.cartesianProduct(other: Iterable<S>, transformer: (first: T, second: S) -> V): List<V> {
return this.flatMap { first -> other.map { second -> transformer.invoke(first, second) } }
}
// Example
fun main(args: Array<String>) {
val ints = listOf(0, 1, 2)
val strings = listOf("a", "b", "c")
// So you could use extension with creating custom transformer
strings.cartesianProduct(ints) { string, int ->
"$int $string"
}.forEach(::println)
// Or use more generic one
strings.cartesianProduct(ints)
.map { (string, int) ->
"$int $string"
}
.forEach(::println)
}
Another (possibly more understandable) alternative to my previous answer. Both achieve the same result:
fun <S, T> List<S>.cartesianProduct(other: List<T>) = this.flatMap { thisIt ->
other.map { otherIt ->
thisIt to otherIt
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With