8

我知道在功能样式中,所有if-else块都被模式匹配替换。但是如何Map在 Scala 中使用模式匹配来处理 s 呢?例如,如何以更实用的方式重写此代码?

  val myMap= getMap()
  if(myMap.contains(x) && myMap.contains(y)) Some(myMap(x) + myMap(y))
    else if(myMap.contains(x + y)){
      val z = myMap(x + y)
      if (z % 2 == 0) Some(z)
      else None
    }
    else None
4

4 回答 4

22

usingif-else对于函数式编程来说是完全可以接受的,因为if-else在 Scala 中只是一个表达式。决定if-else模式匹配和模式匹配的原因应该主要集中在提高可读性上。

这是我重写代码的尝试。我实际上并没有在这里使用模式匹配,而是使用for-comprehension 来对值求和。

def sumOfValues = for{
  mx <- myMap.get(x)
  my <- myMap.get(y)
} yield mx + my

def valueOfSumIfEven = myMap.get(x+y).filter(_ % 2 == 0) 

sumOfValues orElse valueOfSumIfEven
于 2013-08-19T10:26:28.773 回答
3

How about:

myMap.get(x)
    .zip(myMap.get(y))
    .headOption.map(x => x._1 + x._2)
    .orElse(myMap.get(x + y)
    .filter(__ % 2 == 0))
于 2013-08-19T12:31:13.147 回答
3

要直接回答您的问题 - 您可以在以下情况下额外过滤案例:

getMap match {
  case myMap if (myMap.contains(x) && myMap.contains(y)) =>
     Some(myMap(x) + myMap(y))
  case myMap if (myMap.contains(x+y)) =>
    myMap(x+y) match {
      case z if (z % 2 == 0) => Some(z)
      case _                 => None
    }
  case _ => None
}

([编辑:实际上有] 尽管 Scala 中有“else-if”,)这实际上是一种执行 if-else-if-else 的方法(查看生成的类文件,这就是它实际上所做的,而if-else 等效于 java 中的三元 ?: ,当最后一个 else 缺失时隐式返回 Unit )。

于 2013-08-19T10:31:49.143 回答
2

好吧,您可以按如下方式编写测试:

myMap.get(x).flatMap(xVal => myMap.get(y).map(_ + xVal))
            .orElse(myMap.get(x+y).filter(_ % 2 == 0))

但是对于任何试图理解意图的人来说,你已经拥有的可能会更清楚。请注意,第一行(从 flatMap 到结尾)也可以写成便于理解,如@ziggystar 的回答所示)。

如果感觉更清晰,也许可以将模测试部分重写为匹配项:

if(myMap.contains(x) && myMap.contains(y))
    Some(myMap(x) + myMap(y))
else myMap.get(x + y) match {
    case Some(z) if (z % 2 == 0) => Some(z)
    case _ => None
  }
于 2013-08-19T10:31:58.623 回答