【问题标题】:Replace if-else with functional code用功能代码替换 if-else
【发布时间】:2013-08-21 02:21:46
【问题描述】:

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

  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

【问题讨论】:

    标签: scala functional-programming pattern-matching


    【解决方案1】:

    在函数式编程中使用if-else 是完全可以接受的,因为在Scala 中if-else 只是一个表达式。在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
    

    【讨论】:

      【解决方案2】:

      要直接回答您的问题 - 您可以使用附加条件过滤案例:

      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
      }
      

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

      【讨论】:

      • 这看起来并不比您的解决方案好多少......您可能只使用最易于理解的代码 - 功能样式和模式匹配不一定总是最好的解决方案,当命令式样式可读性更好。您的解决方案已经很容易理解了。它可能不像其他解决方案那么酷,但它很简单。
      • else if 是有效的 Scala
      • shhhhame - 你是对的 - 已编辑...所以我可能对 ?: 感到困惑:而且我不知道 Scala 实际上会为缺少的决赛返回一个单元...
      【解决方案3】:

      怎么样:

      myMap.get(x)
          .zip(myMap.get(y))
          .headOption.map(x => x._1 + x._2)
          .orElse(myMap.get(x + y)
          .filter(__ % 2 == 0))
      

      【讨论】:

        【解决方案4】:

        嗯,你可以写你的测试如下:

        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-09-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-04
          • 2014-11-29
          • 2010-10-14
          • 1970-01-01
          相关资源
          最近更新 更多