Assume I have a list of list such this one:
[["1","2","4"], ["5","6"], ["7"]]
I would like to write a function that returns all the possible sequences of numbers by taking only one number from each sublist.
An example of the output:
[["1","5","7"], ["2","5","7"],["2","5",7"] continue...]
I thought about using multiple nested loops but the end result is not going to be "nice to look at".
So I was wondering if there is a cleaner way to deal with this using Kotlin collection APIs
This was the solution I came up with:
fun test():List<List<String>> {
val test = mutableListOf(listOf("1","2","3"), listOf("5"), listOf("6"))
val result:MutableMap<Int,MutableList<List<String>>> = mutableMapOf()
for(i in test.indices) {
if (!result.containsKey(i)) result[i] = mutableListOf()
if (i == 0) test[i].forEach { result[i]!!.add(listOf(it)) }
else {
if (i-2 >= 0) result.remove(i-2)
result[i-1]!!.forEach {prev ->
test[i].forEach {
result[i]!!.add(prev + listOf(it))
}
}
}
}
return result[test.size-1]
}
This is how I modified the solution based on comments input, maybe it could come in handy for someone in the future.
fun test():List<List<String>> {
return result[test.size-1]
}
fun cartesianProduct(input: List<List<*>>): List<List<*>> {
if (input.isEmpty()) return listOf()
return if (input.size == 1) input[0].map { listOf(it) }
else {
val a = input[0]
val b = input[1]
val rest = input.filterIndexed{index, set -> index>1 }.toSet()
(setOf(a, b).plus(rest))
.fold(listOf(listOf<Any?>())) { acc, set ->
acc.flatMap { list -> set.map { element -> list + element } }
}
}
}