I\'m doing a bit of Scala gymnastics where I have Seq[T]
in which I try to find the \"smallest\" element. This is what I do right now:
val leastOrNo
You could always do something like:
case class Foo(num: Int)
val foos: Seq[Foo] = Seq(Foo(1), Foo(2), Foo(3))
val noFoos: Seq[Foo] = Seq.empty
def minByOpt(foos: Seq[Foo]): Option[Foo] =
foos.foldLeft(None: Option[Foo]) { (acc, elem) =>
Option((elem +: acc.toSeq).minBy(_.num))
}
Then use like:
scala> minByOpt(foos)
res0: Option[Foo] = Some(Foo(1))
scala> minByOpt(noFoos)
res1: Option[Foo] = None
For scala < 2.13
Try(seq.minBy(_.something)).toOption
For scala 2.13
seq.minByOption(_.something)
In Haskell you'd wrap the minimumBy call as
least f x | Seq.null x = Nothing
| otherwise = Just (Seq.minimumBy f x)
I have the same problem before, so I extends Ordered and implement the compare function. here is example:
case class Point(longitude0: String, latitude0: String) extends Ordered [Point]{
def this(point: Point) = this(point.original_longitude,point.original_latitude)
val original_longitude = longitude0
val original_latitude = latitude0
val longitude = parseDouble(longitude0).get
val latitude = parseDouble(latitude0).get
override def toString: String = "longitude: " +original_longitude +", latitude: "+ original_latitude
def parseDouble(s: String): Option[Double] = try { Some(s.toDouble) } catch { case _ => None }
def distance(other: Point): Double =
sqrt(pow(longitude - other.longitude, 2) + pow(latitude - other.latitude, 2))
override def compare(that: Point): Int = {
if (longitude < that.longitude)
return -1
else if (longitude == that.longitude && latitude < that.latitude)
return -1
else
return 1
}
}
so if I have a seq of Point I can ask for max or min method
var points = Seq[Point]()
val maxPoint = points.max
val minPoint = points.min
A safe, compact and O(n)
version with Scalaz:
xs.nonEmpty option xs.minBy(_.foo)
Hardly an option for any larger list due to O(nlogn)
complexity:
seq.sortBy(_.something).headOption