Scala的模式匹配集(Scala Pattern Matching with Sets)

2019-08-17 06:07发布

以下是行不通的。

object Foo {
    def union(s: Set[Int], t: Set[Int]): Set[Int] = t match {
        case isEmpty => s
        case (x:xs)  => union(s + x, xs)
        case _       => throw new Error("bad input")
    }
}

错误:未找到:XS型

我怎样才能模式匹配在一组?

Answer 1:

那么, x:xs手段x型的xs ,所以这是行不通的。 但是,唉,你不能模式匹配套,因为套没有定义的顺序。 或者,更务实的态度,因为有上没有提取Set

你总是可以定义自己,虽然:

object SetExtractor {
  def unapplySeq[T](s: Set[T]): Option[Seq[T]] = Some(s.toSeq)
}

例如:

scala> Set(1, 2, 3) match {
     |   case SetExtractor(x, xs @ _*) => println(s"x: $x\nxs: $xs")
     | }
x: 1
xs: ArrayBuffer(2, 3)


Answer 2:

Set不是case class ,没有一个unapply方法。

这两件事意味着你不能直接模式匹配上一Set
更新 :除非你定义自己的提取 Set ,如丹尼尔正确地显示在他的回答)

你应该找到一个替代方案,我建议使用折叠功能

def union(s: Set[Int], t: Set[Int]): Set[Int] = 
    (s foldLeft t) {case (t: Set[Int], x: Int) => t + x}

或者,避免了最明确的类型注释

def union(s: Set[Int], t: Set[Int]): Set[Int] =
  (s foldLeft t)( (union, element) => union + element )

或者更短

def union(s: Set[Int], t: Set[Int]): Set[Int] =
  (s foldLeft t)(_ + _)

这将积累的元素st ,一个逐一添加


折页

下面是文档的折叠操作中,如果需要的话以供参考:

foldLeft[B](z: B)(op: (B, A) ⇒ B): B

应用二元运算符的初始值和该组中的所有元素,从左到右。

注:可能会有不同的结果不同的运行,除非底层集合类型是有序的。 或操作员是联想和交换。

B the result type of the binary operator.
z the start value.
op the binary operator.
returns the result of inserting op between consecutive elements of this set, going left to right with the start value z on the left:

op(...op(z, x_1), x_2, ..., x_n)
where x1, ..., xn are the elements of this set.


Answer 3:

首先,你isEmpty会抓住每一个Set ,因为它在这方面的一个变量。 常量开始在Scala中的大写字母而如果这个条件成立被视为只为常数。 所以小写将指派任何SetisEmpty (您寻找的EmptySet ?)

正如所看到这里 ,似乎是模式匹配不是很理想Set秒。 你应该明确地转换SetListSeqtoList / toSeq

object Foo {
    def union(s: Set[Int], t: Set[Int]): Set[Int] = t.toList match {
        case Nil => s
        case (x::xs)  => union(s + x, xs.toSet)
        case _       => throw new Error("bad input")
    }
}


Answer 4:

这是我能想出:

object Contains {
  class Unapplier[T](val t: T) {
    def unapply(s: Set[T]): Option[Boolean] = Some(s contains t)
  }
  def apply[T](t: T) = new Unapplier(t)
}

object SET {
  class Unapplier[T](val set: Set[T]) {
    def unapply(s: Set[T]): Option[Unit] = if (set == s) Some(Unit) else None
  }
  def apply[T](ts: T*) = new Unapplier(ts.toSet)
}

val Contains2 = Contains(2)
val SET123 = SET(1, 2, 3)

Set(1, 2, 3) match {
  case SET123()         => println("123")
  case Contains2(true)  => println("jippy")
  case Contains2(false) => println("ohh noo")
}


Answer 5:

    t match {
      case s if s.nonEmpty => // non-empty 
      case _ => // empty
    }


文章来源: Scala Pattern Matching with Sets