6

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?

1 Answer 1

12

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.

Sign up to request clarification or add additional context in comments.

2 Comments

You could add to your answer solution with import math.Ordered._. In this case l.sortWith((x,y) => x.bar > y.bar) works as expected.
@senia - Indeed, that would be a good idea. Not sure why I thought one would want to do it the manual way. Reflexive aversion to extra imports, maybe?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.