Лучший способ оценить текущий экстремум в типе коллекции - PullRequest
6 голосов
/ 13 августа 2011

Я сейчас немного устал, поэтому могу упустить очевидное.

У меня есть var _minVal: Option[Double], который должен содержать минимальное значение, содержащееся в коллекции Double с (или Нет, если коллекция пуста)

При добавлении нового элемента в коллекцию я также проверяю, является ли _minVal Нет или больше, чем новый элемент (= кандидат на новый минимум).

Я ушел от

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

(не очень СУХОЙ) до

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

но все же думаю, что я что-то упускаю ...

Ответы [ 2 ]

10 голосов
/ 13 августа 2011

Без Скалаза вы заплатите немного RY.Но я бы написал это как:

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

РЕДАКТИРОВАТЬ

Эрик Торреборре , из Спецификации / Specs2 слава, была достаточно любезна, чтобы продолжить решение Scalaz , которое ускользнуло от меня.Будучи специалистом по тестированию, он написал ответ в формате тестирования вместо обязательного оригинала с побочными эффектами.: -)

Вот версия, использующая _minVal, Double вместо Int, побочные эффекты и некоторые мои извинения теперь, когда Эрик выполнил тяжелую работу.

// 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)
7 голосов
/ 22 августа 2011

Вот обновление к ответу Даниила с использованием Scalaz:

Вот каррированная функция '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)

Затем, используя превосходное объяснение @dibblego , почему Function1 [T, _] является аппликативным функтором , мы можем избежать повторения текущей переменной:

(updateMin <*> orElse).apply(current) === Some(current)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...