我知道在功能样式中,所有if-else
块都被模式匹配所取代。但是我如何处理Scala中模式匹配的Map
?例如,我如何以更多功能样式重写此代码?
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
答案 0 :(得分:19)
使用if-else
对于函数式编程是完全可以接受的,因为Scala中的if-else
只是一个表达式。决定if-else
和模式匹配的原因应该主要集中在提高可读性上。
这是我尝试重写您的代码。我实际上并没有在这里使用模式匹配,而是使用for
- 理解来对值进行求和。
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
答案 1 :(得分:3)
要直接回答您的问题 - 您可以使用附加的if:
过滤案例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's”,但这实际上是一种做if-else-if-else的方式(查看生成的类文件这是什么呢)实际上,而if-else等同于三元?:在java中,当最后的else丢失时隐式返回Unit。)
答案 2 :(得分:2)
怎么样:
myMap.get(x)
.zip(myMap.get(y))
.headOption.map(x => x._1 + x._2)
.orElse(myMap.get(x + y)
.filter(__ % 2 == 0))
答案 3 :(得分:1)
嗯,你可以编写你的测试,如下所示:
myMap.get(x).flatMap(xVal => myMap.get(y).map(_ + xVal))
.orElse(myMap.get(x+y).filter(_ % 2 == 0))
但是,对于任何想要理解意图的人来说,你已经可以更清楚了。请注意,第一行(从flatMap到结尾)也可以写成for-comprehension,如@ 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
}