Scala Sorted by several fields

This question is probably pretty dumb, but I cannot find an example and cannot understand.

I want to compare two Person classes by last, first and middle name in that order. Here's the brain-dead way to do this:

 def compare(that: Person): Int = { val last: Int = lastName.compare(that.lastName) if (last != 0) last else { val first: Int = firstName.compare(that.firstName) if (first != 0) first else middleName.compare(that.middleName) } 

I know there is a much smarter way to do this (perhaps using Ordering ), but I can’t put my finger on it.

Todd

I realized this once when I realized how to access the right things in an order.

 def compare(that: Person): Int = { Ordering.Tuple3(Ordering.String, Ordering.String, Ordering.String).compare( (lastName, firstName, middleName), (that.lastName, that.firstName, that.middleName)) } 

I'm sure I can get away with less explanation, but it works and is compact enough.

+6
source share
1 answer

Option 1: sortBy

Using the sortBy method, this can be quite simple:

 case class Person(first: String, middle: String, last: String) val personList = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith")) personList.sortBy{ case Person(f,m,l) => (l,f,m) } 

Option 2: Order Extension [Person]

Extending Ordered[Person] , the class will know how to sort itself, so we get things like sorted , min and max for free:

 case class Person(first: String, middle: String, last: String) extends Ordered[Person] { def compare(that: Person): Int = (last compare that.last) match { case 0 => (first compare that.first) match { case 0 => middle compare that.middle case c => c } case c => c } } val personList = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith")) personList.sorted personList.min personList.max 

Option 3: Implicit ordering

If you use implicit Ordering , you get sorted , min , etc. without reference to a specific order of your source class. This denouement may be convenient or annoying depending on your particular case.

 case class Person(first: String, middle: String, last: String) implicit val ord = new Ordering[Person] { def compare(self: Person, that: Person): Int = (self.last compare that.last) match { case 0 => (self.first compare that.first) match { case 0 => self.middle compare that.middle case c => c } case c => c } } val personList = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith")) personList.sorted personList.min personList.max 
+16
source

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


All Articles