web-dev-qa-db-ja.com

Scala匿名関数でパターンマッチングを行うためのより明確な方法はありますか?

私は次のようなコードを書いています。

val b = a map (entry =>
    entry match {
        case ((x,y), u) => ((y,x), u)
    }
)

これがうまくいった場合のみ、私はそれを別の方法で書きたいと思います:

val c = a map (((x,y) -> u) =>
    (y,x) -> u
)

これに近いものを入手する方法はありますか?

36
Owen

信じられないかもしれませんが、これは機能します。

val b = List(1, 2)
b map {
  case 1 => "one"
  case 2 => "two"
}

単純なケースではp => p matchをスキップできます。だからこれはうまくいくはずです:

val c = a map {
  case ((x,y) -> u) => (y,x) -> u
}
56
sblundy

あなたの例では、あなたがしようとしているかもしれない3つの微妙に異なるセマンティクスがあります。

  1. コレクションにマッピングし、パターンに一致する各要素を変換します。一致しない要素がある場合は、例外をスローします。これらのセマンティクスは、

    val b = a map { case ((x, y), u) => ((y, x), u) }
    
  2. コレクションにマッピングし、パターンに一致する各要素を変換します。一致しない要素をサイレントに破棄します。

    val b = a collect { case ((x, y), u) => ((y, x), u) }
    
  3. コレクションをマッピングし、安全に分解してから各要素を変換します。これらは私が次のような表現に期待する意味です

    val b = a map (((x, y), u) => ((y, x), u)))  
    

    残念ながら、Scalaでこれらのセマンティクスを実現する簡潔な構文はありません。代わりに、自分で分解する必要があります。

    val b = a map { p => ((p._1._2, p._1._1), p._2) }
    

    解体のために値の定義を使用したくなるかもしれません:

    val b = a map { p => val ((x,y), u) = p; ((y, x), u) }
    

    ただし、このバージョン 明示的なパターンマッチングを使用するバージョンより安全ではありません 。このため、安全な構造化セマンティクスが必要な場合、最も簡潔な解決策は、コレクションを明示的に入力して意図しない拡大を防ぎ、明示的なパターンマッチングを使用することです。

    val a: List[((Int, Int), Int)] = // ...
    // ...
    val b = a map { case ((x, y), u) => ((y, x), u) }
    

    aの定義がその使用から離れている場合(別のコンパイル単位など)、マップの呼び出しでそのタイプを指定することにより、リスクを最小限に抑えることができます。

    val b = (a: List[((Int, Int), Int)]) map { case ((x, y), u) => ((y, x), u) }
    
22
Aaron Novstrup

引用した例では、最もクリーンなソリューションは次のとおりです。

val xs = List((1,2)->3,(4,5)->6,(7,8)->9)
xs map { case (a,b) => (a.swap, b) }
10
Kevin Wright
val b = a map { case ((x,y), u) => ((y,x), u) }
4