If I have a case class like this
case class Foo(bar: Option[String])
why does this work
scala> val l = List(Foo(Some("b")), Foo(Some("a")), Foo(Some("c")))
l: List[Foo] = List(Foo(Some(b)), Foo(Some(a)), Foo(Some(c)))
scala> l.sortBy(_.bar)
res1: List[Foo] = List(Foo(Some(a)), Foo(Some(b)), Foo(Some(c)))
but not this
scala> l.sortWith((x,y) => x.bar > y.bar)
<console>:11: error: value > is not a member of Option[String]
l.sortWith((x,y) => x.bar > y.bar)
If I want to sort a List of Option[String] in descending order, is it just simpler to use sortBy and then reverse the list?
It's because sorted but not sortWith takes an implicit parameter of type Ordering, and Ordering knows about options. With sortWith, you're on your own. And with < you're also on your own.
You can access the same machinery in a clunky fashion:
l.sortWith((a,b) => Ordering[Option[String]].gt(a.bar,b.bar))
or get the nicer version with an import (but now you'll be able to compare Options anywhere based on their contents; hopefully that is what you want):
import scala.math.Ordered._
l.sortWith((a,b) => a.bar > b.bar)
The first is such a mouthful that unless you're really pressed for performance, it's easier to just .sorted.reverse.. (And if you are really pressed for performance, you'd probably be better off handling the option logic manually, e.g. a.bar.isEmpty || !b.bar.isEmpty || a.bar.get < b.bar.get.)
If you're going to do multiple sorts, it's hard to beat the second for clarity. For just one test, I'd still probably favor .sorted.reverse.
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