Vil*_*tas 13 scala scala-option
基本上我正在寻找最像scala的方式来做以下事情:
def sum(value1: Option[Int], value2: Option[Int]): Option[Int] =
if(value1.isDefined && value2.isDefined) Some(value1.get + value2.get)
else if(value1.isDefined && value2.isEmpty) value1
else if(value1.isEmpty && value2.isDefined) value2
else None
Run Code Online (Sandbox Code Playgroud)
这给出了正确的输出:
sum(Some(5), Some(3)) // result = Some(8)
sum(Some(5), None) // result = Some(5)
sum(None, Some(3)) // result = Some(3)
sum(None, None) // result = None
Run Code Online (Sandbox Code Playgroud)
然而,总结两个以上的选项,我必须使用太多ifs或使用某种循环.
编辑-1:
在写这个问题时,我想出了一个答案:
def sum2(value1: Option[Int], value2: Option[Int]): Option[Int] =
value1.toList ::: value2.toList reduceLeftOption { _ + _ }
Run Code Online (Sandbox Code Playgroud)
这个看起来非常惯用于我没有经验的眼睛.这甚至可以使用两个以上的值.可以在不转换为列表的情况下执行相同的操作吗?
EDIT 2:
我最终得到了这个解决方案(感谢ziggystar):
def sum(values: Option[Int]*): Option[Int] =
values.flatten reduceLeftOption { _ + _ }
Run Code Online (Sandbox Code Playgroud)
编辑-3:
Landei的另一个选择:
def sum(values: Option[Int]*): Option[Int] =
values collect { case Some(n) => n } reduceLeftOption { _ + _ }
Run Code Online (Sandbox Code Playgroud)
zig*_*tar 10
怎么样:
scala> def sum(values: Option[Int]*): Option[Int] = values.flatten match {
| case Nil => None
| case l => Some(l.sum)
| }
sum: (values: Option[Int]*)Option[Int]
scala> sum(Some(1), None)
res0: Option[Int] = Some(1)
scala> sum(Some(1), Some(4))
res1: Option[Int] = Some(5)
scala> sum(Some(1), Some(4), Some(-5))
res3: Option[Int] = Some(0)
scala> sum(None, None)
res4: Option[Int] = None
Run Code Online (Sandbox Code Playgroud)
如果所有参数都是None,那么返回0也许是理智的.在这种情况下,函数将减少到values.flatten.sum.
scala> def sum(a: Option[Int], b: Option[Int]) = (a,b) match {
| case (Some(x), Some(y)) => Some(x + y)
| case (Some(x), None) => Some(x)
| case (None, Some(y)) => Some(y)
| case _ => None
| }
sum: (a: Option[Int],b: Option[Int])Option[Int]
scala> sum(Some(5), Some(3))
res0: Option[Int] = Some(8)
scala> sum(Some(5), None)
res1: Option[Int] = Some(5)
scala> sum(None, Some(3))
res2: Option[Int] = Some(3)
scala> sum(None, None)
res3: Option[Int] = None
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是
def sum(values: Option[Int]*): Int = values.collect{case Some(n) => n}.sum
Run Code Online (Sandbox Code Playgroud)
虽然在当前情况下flatten显然更方便,但collect版本更灵活,因为它允许执行映射并具有额外的过滤条件或复杂模式.例如,想象你想要在值中得到所有偶数的平方和:
values.collect{case Some(n) if n mod 2 == 0 => n*n}.sum
Run Code Online (Sandbox Code Playgroud)
您可以使用以下事实使其非常简洁,即有一个Semigroup实例可以Option完全满足您的需求。您可以使用scalaz或猫。这是一个使用示例cats:
import cats.std.option._
import cats.syntax.semigroup._
import cats.std.int._
Option(1) |+| Option(2) // Some(3)
Option(1) |+| None // Some(1)
None |+| Option(2) // Some(2)
Run Code Online (Sandbox Code Playgroud)
所以你sum变成:
def sum(v1: Option[Int], v2: Option[Int]): Option[Int] = v1 |+| v2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3960 次 |
| 最近记录: |