如何用Option或PartialFunction简化Scala方法,移除flatMap中的else分支
优化Scala代码:移除flatMap中的else分支并简化逻辑
我来帮你搞定这个问题——你想去掉flatMap里的else分支,同时避免生成无用的price为0的BidItem,用Option就能完美解决这个问题,还能顺便简化后续的过滤逻辑。
修改后的完整代码
def getBids(rawBids: RDD[List[String]], exchangeRates: Map[String, Double]): RDD[BidItem] = { rawBids.filter(bidList => !bidList(2).matches("ERROR_REGEXP")) .flatMap(bidList => { Constants.TARGET_LOSAS.flatMap { losa => val indexOfLosa = Constants.BIDS_HEADER.indexOf(losa) val priceStr = bidList(indexOfLosa) // 仅当条件满足时生成有效的BidItem,否则返回None(会被flatMap自动忽略) Option.when(priceStr != null && !priceStr.isEmpty && isDoubleNumber(priceStr)) { BidItem(bidList.head, bidList(1), losa, priceStr.toDouble) } } }) .map(unit => { val convertedPrice = usdToEur(unit.price, unit.bidDate, exchangeRates) val convertedDate = changeDateFormat(unit.bidDate) BidItem(unit.motelId, convertedDate, unit.loSa, convertedPrice) }) }
关键改动说明
用Option替代if-else生成可选元素
- 使用
Option.when(Scala 2.13+支持):当括号内的条件成立时,返回包装了有效BidItem的Some;条件不成立时返回None。如果你的项目用的是Scala 2.12及以下版本,直接换成if (condition) Some(item) else None即可,效果完全一样。
- 使用
把TARGET_LOSAS的map改成flatMap
- 因为现在每个losa对应的是
Option[BidItem],flatMap会自动展开Some里的元素,同时忽略None,这样就不会生成那些price为0的无效项了。
- 因为现在每个losa对应的是
移除多余的filter步骤
- 既然不满足条件的项根本不会被生成,后面的
.filter(unit => unit.price != 0)就完全没必要了,既能简化代码,还能提升一点执行效率。
- 既然不满足条件的项根本不会被生成,后面的
修正了原代码的类型语法错误
- 原代码里的
List["String"]和Map["String", Double]写法有误,Scala里的泛型参数不需要加引号,已经改成了正确的List[String]和Map[String, Double]。
- 原代码里的
另一种可选写法(用for推导式)
如果你更喜欢for推导式的风格,也可以这样写,逻辑是完全一致的:
Constants.TARGET_LOSAS.flatMap { losa => val indexOfLosa = Constants.BIDS_HEADER.indexOf(losa) val priceStr = bidList(indexOfLosa) for { _ <- Option.when(priceStr != null && !priceStr.isEmpty && isDoubleNumber(priceStr)) } yield BidItem(bidList.head, bidList(1), losa, priceStr.toDouble) }
这样修改后,代码不仅去掉了讨厌的else分支,逻辑也更清晰,还减少了不必要的中间元素生成,一举多得~
内容的提问来源于stack exchange,提问作者Pavel Orlov
相关产品推荐
相关产品推荐

