我有一对Option[Int]
,想要找到两个值中的最小值,如果它们都存在,否则只是其中之一。假设我有一个函数minOption
:
def minOption(a: Option[Int], b: Option[Int]): Option[Int]
我想要的是以下输入到输出的映射:
(Some(a), Some(b)) => Some(Math.min(a,b))
(Some(a), None) => Some(a)
(None, Some(b)) => Some(b)
(None, None) => None
有一种简单的方法吗?我无法想出使用嵌套模式匹配的明显方式。
我认为这在scalaz
中应该是微不足道的,但我对它还不是很熟悉,也找不到方法。
答案 0 :(得分:6)
有一个用Label.MinVal标记的东西的半群,它选择最小值:
scala> import scalaz._ ; import Scalaz._ ; import Tags._
import scalaz._
import Scalaz._
import Tags._
scala> MinVal(3).some |+| MinVal(1).some
res0: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(1)
scala> MinVal(3).some |+| none[Int @@ MinVal]
res1: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(3)
scala> none[Int @@ MinVal] |+| none[Int @@ MinVal]
res2: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = None
在上文中,Int @@ MinVal
是Int
的子类型,已使用MinVal
“标记”,这有助于选择正确的半群。 MinVal(x: Int)
返回类型为Int @@ MinVal
的x。 x.some
与Some(x)
类似,但类型为Option
而不是Some
,这有助于类型推断(有一个Semigroup for Option,但不适用于Some),类似none[T]
返回None
,但其类型为Option[T]
而不是None
(由于同样的原因,没有半群为无,但有一个用于选项)< / p>
如果有两个以上,也许你有一个列表,你可以使用suml
:
scala> List(MinVal(2).some, None, MinVal(3).some, None, MinVal(1).some).suml
res5: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(1)
答案 1 :(得分:3)
我认为您不需要Scalaz:假设您的选项包含在列表中(也使用varargs)
def findMinOpt(li: List[Option[Int]]): Option[Int] =
{
val listwithoutOptions = li.flatten
listwithoutOptions.reduceLeftOption(_ min _)
}
def findMinOptVarArgs(li: Option[Int]*): Option[Int] =
{
val listwithoutOptions = li.flatten
listwithoutOptions.reduceLeftOption(_ min _)
}