在集合类型中获得当前极值的最佳方法

时间:2011-08-12 20:31:42

标签: scala max option min

我现在有点累了所以我可能会错过这个显而易见的事情。

我有一个var _minVal: Option[Double],它应该包含Double s集合中包含的最小值(如果集合为空,则为None)

在向集合中添加新项目时,我也检查_minVal是否为None或大于新项目(=新mimimum候选项)。

我已离开

_minVal = Some(_minVal match {
    case Some(oldMin) => if (candidate < oldMin) candidate
                         else                    oldMin
    case None         =>                         candidate
})

(不是很干)

_minVal = Some(min(_minVal getOrElse candidate, candidate))

但仍然认为我可能会遗漏某些东西......

2 个答案:

答案 0 :(得分:10)

如果没有Scalaz,你将支付一些RY。但我会把它写成:

_minVal = _minVal map (candidate min) orElse Some(candidate)

修改

Eric Torreborre / Specs成名的{p> Specs2非常友好,可以追求我未能找到的Scalaz解决方案。作为一个测试框架的人,他以测试格式编写答案,而不是命令性的副作用原文。 : - )

以下是使用_minValDouble而不是Int的版本,副作用以及我的一些曲折现在,Eric已经做了很多努力。

// From the question (candidate provided for testing purposes)
var _minVal: Option[Double] = None
def candidate = scala.util.Random.nextDouble

// A function "min"
def min = (_: Double) min (_: Double)

// A function "orElse"
def orElse = (_: Option[Double]) orElse (_: Option[Double])

// Extract function to decrease noise
def updateMin = _minVal map min.curried(_: Double)

// This is the Scalaz vesion for the above -- type inference is not kind to it
// def updateMin = (_minVal map min.curried).sequence[({type lambda[a] = (Double => a)})#lambda, Double]

// Say the magic words
import scalaz._
import Scalaz._   

def orElseSome = (Option(_: Double)) andThen orElse.flip.curried
def updateMinOrSome = updateMin <*> orElseSome

// TAH-DAH!
 _minVal = updateMinOrSome(candidate)

答案 1 :(得分:7)

以下是使用Scalaz对Daniel的回答的更新:

这是一个咖喱'min'功能:

def min = (i: Int) => (j: Int) => if (i < j) i else j 

和2个变量:

// the last minimum value
def lastMin: Option[Int] = None

// the new value
def current = 1

现在让我们定义2个新函数

// this one does the minimum update
def updateMin = (i: Int) => lastMin map (min(i))

// this one provides a default value if the option o2 is not defined
def orElse = (o1: Int) => (o2: Option[Int]) => o2 orElse Some(o1)

然后使用why Function1[T, _] is an applicative functor的@dibblego的优秀解释,我们可以避免重复“当前”变量:

(updateMin <*> orElse).apply(current) === Some(current)