Is there a standard library function which would g...
# announcements
d
Is there a standard library function which would get me all possible combinations of elements in a list?
Copy code
listOf(1, 2, 3) -> (1, 2); (1,3); (2,1); (2,3); (3,1); (3,2)
r
No, because that's not necessarily a well defined concept. For example, why didn't you count
(1, 1)
,
(2, 2)
, or
(3, 3)
as combinations? Why did you count
(1, 2)
and
(2, 1)
as separate combinations?
Any of those assumptions (and their inverses) are equally valid in different contexts.
👍 1
You need to choose which assumptions make sense for your use case, and implement the logic accordingly (luckily K makes it easy to implement any of those combinations succinctly).
d
Thank you for your reply! And indeed, there are quite a lot of asumptions. So a good thing that isnt there
d
I am pretty sure there is a strict definition of combination in mathematics, so no assumptions needed to be made
python has combinations and permutations in its standard library
and if kotlin wants to be go-to language for data people it needs this kind of functionality
f
yeah I always found it weird that Java didn't have a Collection.permutations function, there's one in Guava though
r
@Daniel Not sure if it's what you are looking for but that sounds like:
Copy code
object AllCombinations {
  @JvmStatic
  fun main(args: Array<String>) {
    val list = listOf(1, 2, 3)
    val allCombinations: List<Pair<Int, Int>> =
      list.flatMap { a ->
        list.map { b ->
          a to b
        }
      }
    println(allCombinations)
    //[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
  }
}
That is just
flatMap
and
map
over a
List
r
@Dias There is, but programming isn't mathematics, and often your use case will be in direct conflict with the mathematical definition (usually based around the fact that there is a pretty clear definition of equality in math, but not so much in programming).
r
@Daniel The imperative version which exists in many langs as generators or for comprehensions is also available in Kotlin with Arrow:
Copy code
import arrow.instances.list.monad.binding

val allCombinations2: List<Pair<Int, Int>> = 
  binding {
    val el1 = list.k().bind()
    val el2 = list.k().bind()
    el1 to el2
  }
d
IIRC Groovy has both
permutations
and
combinations
in stdlib, would be nice to have them in Kotlin.
d
@raulraja First of all thank you for your code snippets! Its great to see that if the need arises there are always well written libraries which will do the trick.
r
@Ruckus I think programming can get pretty close to mathematics for most problem definitions. That doesn't mean one can't solve problems ad-hoc with no math involved with programing. When applying Typed FP it's close to mathematics and the abstractions in use are based on math laws regarding composition and identity
r
Indeed, and the more you adhere to FP principles the closer you get (which is probably why you Arrow guys like bringing up math so much 🧌). However, Kotlin isn't a purely FP or mathematical modeling language, so I tend to favor keeping such constructs out of the #C0B8Q383C in favor of other libraries, as many of the more mathematical assumptions break down in a lot of "real world" use cases. Note: I'm not implying that math isn't real world or that a mathematical solution wouldn't be better in a lot of such cases, just that, for various reasons (hacks due to unrealistic time constraints, interop with legacy codebases, etc.), it's often not the case.
a
I think in situations like this, its possible to have either an intermediate type/object representing permutations or combinations with additional methods to specify things like repetition, size, and eventually get it as a collection or stream/sequence. Alternately named parameters with defaults could be used. Ideally there would be default assumptions that most people expect, possibly what other languages like groovy or python are using. However even if there isn't, having the option to change it right there would cover most if not all cases and remove any ambiguity. For me it is also more easily readable than a flatmap operation, though I agree some people would prefer flatmap/map/loop approach since it is relatively trivial. Having it in stdlib also makes it more reliable/predictable. Since different libraries could have different implementations (assumptions) that need to be checked. Looking back at my limited experience though, I've only used permutations and that was for few unit tests. So I can see it being left out of stdlib due to not needing it often.