18

以下は動作しません。

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

セット全体でパターン マッチを行うにはどうすればよいですか?

4

5 に答える 5

21

まあ、type のx:xs手段なので、うまくいきません。しかし、残念ながら、セットには順序が定義されていないため、一致セットをパターン化することはできません。または、より実用的に言えば、 にはエクストラクタがないためです。xxsSet

ただし、いつでも独自に定義できます。

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)
于 2013-03-01T21:44:24.343 に答える
7

Setではなくcase class、メソッドがありませんunapply

これら 2 つのことは、 で直接パターン マッチできないことを意味します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)(_ + _)

sこれにより、 overの要素が蓄積tされ、1 つずつ追加されます


折りたたみ

参照が必要な場合は、折りたたみ操作のドキュメントを次に示します。

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.
于 2013-03-01T18:02:16.420 に答える
6

まず第一に、このコンテキストでは変数であるため、すべてisEmptyをキャッチします。SetScala では定数は大文字で始まり、この条件が成立する場合にのみ定数として扱われます。したがって、小文字は anySetを割り当てますisEmpty(探していましたEmptySetか?)

ここに見られるように、パターン マッチングは s にはあまり適していないようですSet。おそらく明示的にSetListまたはSeq( toList/ 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")
    }
}
于 2013-03-01T17:59:45.083 に答える
2

これは私が思いつくことができるものです:

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")
}
于 2013-10-02T20:28:57.940 に答える