The best way to get the current extremum in a collection type

I'm currently a little tired, so maybe I'm missing the obvious.

I have var _minVal: Option[Double] , which should contain the minimum value contained in the Double collection (or None if the collection is empty)

When adding a new item to the collection, I also check if _minVal either None or more than the new item (= candidate for the new minimum).

Ive left

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

(not very DRY) to

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

but still think that I can miss something ...

+6
source share
2 answers

Without Scalaz, you are going to pay RY. But I would write this as:

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

EDIT

Eric Torreborr , Specs / Specs2 , was enough to pursue a Scalaz decision that eluded me. As a testing guy, he wrote the answer in a test format instead of the obligatory, side effect of the original. :-)

Here's a version that uses _minVal , Double instead of Int , side effects and some of the highlights now that Eric has done the hard work.

 // 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) 
+10
source

Here is an update of Daniel's answer using Scalaz:

The min 'min' function is used here:

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

And 2 variables:

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

Now we define two new functions

 // 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) 

Then, using the excellent @dibblego explanation of why Function1 [T, _] is an application functor , we can avoid repeating the β€œcurrent” variable:

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

Source: https://habr.com/ru/post/894944/


All Articles