Lun*_*ore 9 functional-programming scala
任何人都可以帮助这个Scala新手吗?以前,我们在具有以下数量的实体列表中汇总了一些数量:
sum = entities.foldLeft(0.0)(_ + _.quantity)
Run Code Online (Sandbox Code Playgroud)
现在数量是一个Option[Double],总和也是.如何使用惯用的Scala转换它?
如果任何实体的数量是None那么总和也应该是None.否则总和应该是Some(total).
编辑:将此内容放入单元测试中,以便我可以尝试所有答案.请注意,如果任何数量为无,我确实需要结果为无,因为缺少数量意味着我们还没有完成,所以总数应该反映这一点.即使你没有得到正确的答案,如果你帮助引导我或其他人,或者帮助我学习新的东西,我会赞成.
编辑:@ sepp2k赢得了工作解决方案和解释.感谢大家的学习!
您可以使用Option's flatMap和map方法组合两个Options,以便结果将是Some(f(x,y))两个Options Some(x)和/ Some(y)或None其他.
entities.foldLeft(Some(0.0):Option[Double]) {
(acco, x) => acco.flatMap(acc => x.quantity.map(_ + acc))
}
Run Code Online (Sandbox Code Playgroud)
编辑以回应您的评论:
这是一个示例用法:
scala> case class Foo(quantity:Option[Double]) {}
defined class Foo
scala> val entities: List[Foo] = List(Foo(Some(2.0)), Foo(Some(1.0)), Foo(None))
scala> entities.foldLeft(Some(0.0):Option[Double]) {
(acco, x) => acco.flatMap(acc => x.quantity.map(_ + acc))
}
res0: Option[Double] = None
scala> val entities: List[Foo] = List(Foo(Some(2.0)), Foo(Some(1.0)))
scala> entities.foldLeft(Some(0.0):Option[Double]) {
(acco, x) => acco.flatMap(acc => x.quantity.map(_ + acc))
}
res1: Option[Double] = Some(3.0)
Run Code Online (Sandbox Code Playgroud)
所以,是的,None如果有任何实体,它将返回None.
关于map和flatMap:
map采用f类型的函数A => B并返回Some(f(x))for Some(x)和Nonefor None.
xo.flatMap(f)其中f是类型的函数A => Option[B]和xo是Option[A],返回Some(y)IFF xo是Some(x)和f(x)是Some(y).在其他情况下(即,如果xo是None或者f(x)是None)返回None.
所以表达式acco.flatMap(acc => x.quantity.map(_ + acc))返回y + acciff x.quantityis Some(y)和accois Some(acc).如果一个或两个的x.quantity和acco都是None,结果将是无法比拟的.因为这是在折叠内,这意味着对于下一次迭代,值acco也将是None,因此最终结果将是None.