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 leastOrNone = seq.reduceOption { (best, current) =>
if (current.something < best.something) current
else best
}
It works fine, but I'm not quite satisfied - it's a bit long for such a simple thing, and I don't care much for "if"s. Using minBy
would be much more elegant:
val least = seq.minBy(_.something)
... but min
and minBy
throw exceptions when the sequence is empty. Is there an idiomatic, more elegant way of finding the smallest element of a possibly empty list as an Option
?
seq.reduceOption(_ min _)
does what you want?
Edit: Here's an example incorporating your _.something
:
case class Foo(a: Int, b: Int)
val seq = Seq(Foo(1,1),Foo(2,0),Foo(0,3))
val ord = Ordering.by((_: Foo).b)
seq.reduceOption(ord.min) //Option[Foo] = Some(Foo(2,0))
or, as generic method:
def minOptionBy[A, B: Ordering](seq: Seq[A])(f: A => B) =
seq reduceOption Ordering.by(f).min
which you could invoke with minOptionBy(seq)(_.something)
Starting Scala 2.13
, minByOption
/maxByOption
is now part of the standard library and returns None
if the sequence is empty:
seq.minByOption(_.something)
List((3, 'a'), (1, 'b'), (5, 'c')).minByOption(_._1) // Option[(Int, Char)] = Some((1,b))
List[(Int, Char)]().minByOption(_._1) // Option[(Int, Char)] = None
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
Also, it is available to do like that
Some(seq).filter(_.nonEmpty).map(_.minBy(_.something))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With