是否可以在Iterable上进行模式匹配

时间:2018-10-11 13:36:52

标签: scala pattern-matching

它提供了一种优雅的方式来对scala Iterable[A]集合进行模式匹配,以检查其是否为空,是否仅包含一个元素(并获取),是否完全包含N个元素(并获取它们) ,如果它至少包含一个或多个元素(并获取一个或多个元素),等等。

使用List很简单,但是我无法使用Iterable的等效功能。

2 个答案:

答案 0 :(得分:2)

您要通过以下方式进行模式匹配吗?

val it: Iterable[Int] = ...
it match {
  case Iterable(1, a, b) => ...
  case Iterable(a, b) => ...
  case Iterable() =>
}

如果是,实际上您无法执行此操作,因为Iterable的伴随对象没有unapplySeq方法。因此,最简单的方法是将Iterable显式转换为Seq

val it: Iterable[Int] = ...
it.toSeq match {
  case Seq(1, a, b) => ...
  case Seq(a, b) => ...
  case Seq() =>
}

或者,如果您不想每次都手动将Iterable转换为Seq,则可以使用以下方法:

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() =>
}

但是请注意,基础集合可能不是Seq。这种方法可能导致将整个Iterable复制到新集合中。

编辑:

Iterable可能是无限的。在这种情况下,.toSeq可能会使您的程序崩溃。 因此,最安全的方法是在模式匹配之前调用.take(n)

答案 1 :(得分:-1)

如何?

   object Example extends App {

     val myIterable: Iterable[Int] = List(1,2).toIterable

     myIterable match {
        case Nil =>
            println(s" list is empty")
        case a::Nil =>
            println(s" list contains 1 elements $a")
        case a::b::Nil =>
            println(s" list contains 2 elements $a and $b")
    }
  }