It there an elegant way to pattern match on a scala Iterable[A] collection, to check if it's empty, if it contains exactly one element (and get it), if it contains exactly N elements (and get them), if it contains at least one or more elements (and get it or them), and so on.
With List it's trivial, but I'm not able to have the equivalent for Iterable working.
Do you want to do pattern matching in the following way?
val it: Iterable[Int] = ...
it match {
case Iterable(1, a, b) => ...
case Iterable(a, b) => ...
case Iterable() =>
}
If yes, actually you can't do it because Iterable's companion object doesn't have unapplySeq method. So the easiest way to do so is explicitly converting Iterable to Seq:
val it: Iterable[Int] = ...
it.toSeq match {
case Seq(1, a, b) => ...
case Seq(a, b) => ...
case Seq() =>
}
Or if you don't want to convert Iterable to Seq every time by hand, you can use something like this:
object iterable {
def unapplySeq[A](it: Iterable[A]): Option[Seq[A]] = Some(it.toSeq)
}
val it: Iterable[Int] = ...
it match {
case iterable(1, a, b) => ...
case iterable(a, b) => ...
case iterable() =>
}
But be aware that underlying collection may not be a Seq. This approach may lead to copying the whole Iterable into a new collection.
EDIT:
Iterable may be infinite. In this case .toSeq may crash your program.
So the safest way will be calling .take(n) before pattern matching
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