如何改进用Scala编写的这段代码?

时间:2015-04-22 20:20:20

标签: scala

我想知道如何改进此代码以使其更具可读性和流畅性。感谢您的帮助,谢谢。

// filter DWT based on Zone
val dwtListZon = query.zoneOpt match {
  case None => dwtListStn
  case Some(zon) => {
    if (zon.crwStn333 == "all") {
      dwtListStn
    }
    dwtListStn.filter(_.crwStnAbbr3 == zon.crwStnAbbr3)
  }
}

我只想了解这个代码应该如何在简单性和可读性方面以更具说明性(如果可能)的方式编写。

下面的答案显示了做同样事情的不同风格,这也有助于扩大我对FP和Scala的总体洞察力。谢谢你!

3 个答案:

答案 0 :(得分:5)

您可能还会考虑fold上提供的Option功能。对于具有默认值的Options来说,它通常是一个很好的语法,你可以使用优雅的部分函数语法:

query.zoneOpt.fold(dwtListStn) { 
    case zon if zon.crwStn333 == "all" => dwtListStn
    case zon => dwtListStn.filter(_.crwStnAbbr3 == zon.crwStnAbbr3)
} 

这里的另一个一般策略是翻转操作。所有逻辑分支都返回dwtListStn的过滤或未过滤版本,因此您可以将整个操作视为filter

dwtListStn.filter { dwt => 
    query.zoneOpt match {
        case Some(zone) if zone.crwStn333 == "all" => false
        case Some(zone) => dwt.crwStnAbbr3 == zon.crwStnAbbr3
        case None => false
    }
}

答案 1 :(得分:2)

val dwtListZon = query.zoneOpt filter (_.crwStn333 != "all") map (zon =>
 dwtListStn.filter(_.crwStnAbbr3 == zon.crwStnAbbr3) ) getOrElse dwtListStn

或者如果你想要可读性

val filteredSomething = for(zon <- query.zoneOpt if zon.crwStn333 != "all")
    yield dwtListStn.filter(_.crwStnAbbr3 == zon.crwStnAbbr3)
val dwtListZon = filteredSomething getOrElse dwtListStn

答案 2 :(得分:1)

正常匹配也很清楚。如果条件只是反转:

query.zoneOpt match {
   case Some(zon) if (zon.crwStn333 != "all") => 
      dwtListStn.filter(_.crwStnAbbr3 == zon.crwStnAbbr3)
   case _ =>
      dwtListStn
}