在Scala匿名函数中是否有更简洁的模式匹配方法?

Owe*_*wen 36 scala pattern-matching

我发现自己编写如下代码:

val b = a map (entry =>
    entry match {
        case ((x,y), u) => ((y,x), u)
    }
)
Run Code Online (Sandbox Code Playgroud)

我想以不同的方式写它,如果只有这个工作:

val c = a map (((x,y) -> u) =>
    (y,x) -> u
)
Run Code Online (Sandbox Code Playgroud)

有什么方法可以让我接近这个吗?

sbl*_*ndy 55

信不信由你,这有效:

val b = List(1, 2)
b map({case 1 => "one"
       case 2 => "two"})
Run Code Online (Sandbox Code Playgroud)

您可以跳过p => p match简单的情况.所以这应该工作:

val c = a map {case ((x,y) -> u) =>
    (y,x) -> u
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以跳过一对parens/bracket:`b map {case 1 =>"one"; case 2 =>"two"}` (21认同)

Aar*_*rup 22

在您的示例中,您可能会有三种略有不同的语义.

  1. 映射集合,转换与模式匹配的每个元素.如果任何元素不匹配,则抛出异常.这些语义是通过实现的

    val b = a map { case ((x, y), u) => ((y, x), u) }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 映射集合,转换与模式匹配的每个元素.无声地丢弃不匹配的元素:

    val b = a collect { case ((x, y), u) => ((y, x), u) }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 映射集合,安全地解构然后转换每个元素.这些是我希望表达式的语义

    val b = a map (((x, y), u) => ((y, x), u)))  
    
    Run Code Online (Sandbox Code Playgroud)

    不幸的是,在Scala中没有简洁的语法来实现这些语义.相反,你必须自己解构:

    val b = a map { p => ((p._1._2, p._1._1), p._2) }
    
    Run Code Online (Sandbox Code Playgroud)

    有人可能会想要使用值定义进行解构:

    val b = a map { p => val ((x,y), u) = p; ((y, x), u) }
    
    Run Code Online (Sandbox Code Playgroud)

    但是,此版本不比使用显式模式匹配的版本更安全.因此,如果您需要安全解构语义,最简洁的解决方案是显式键入您的集合以防止意外扩展并使用显式模式匹配:

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

    如果a定义远离其使用(例如在单独的编译单元中),则可以通过在地图调用中归类其类型来最小化风险:

    val b = (a: List[((Int, Int), Int)]) map { case ((x, y), u) => ((y, x), u) }
    
    Run Code Online (Sandbox Code Playgroud)


Kev*_*ght 10

在您引用的示例中,最干净的解决方案是:

val xs = List((1,2)->3,(4,5)->6,(7,8)->9)
xs map { case (a,b) => (a.swap, b) }
Run Code Online (Sandbox Code Playgroud)