Using minBy and maxBy of Scala Collections API

The Scaladoc of minBy and maxBy which were added in Scala 2.9 is quite rudimentary:

def minBy[B](f: (A) ⇒ B)(implicit cmp: Ordering[B]): A
def maxBy[B](f: (A) ⇒ B)(implicit cmp: Ordering[B]): A

I tried to understand these higher order functions and come up with a use case which makes sense:

scala> case class Person(name: String, age: Int)
defined class Person

scala> val persons = Seq(
| Person(“Young”, 17),
| Person(“MidLifeCrisis”, 40),
| Person(“Wise”, 99)
| )
persons: Seq[Person] = List(Person(Young,17), Person(MidLifeCrisis,40), Person(Wise,99))

scala> persons.minBy(_.age)
res23: Person = Person(Young,17)

scala> persons.maxBy(_.age)
res24: Person = Person(Wise,99)

The function passed to minBy and maxBy returns a value which is then used for finding the min/max element of the collection.

Note: The implicit parameter of type Ordering[Int] is defined in the companion object of the scala.math.Ordering trait.

Because there is no Ordering[Person] defined min and minBy do not work on persons objects. Scala gives a excellent error message:

scala> persons.min
:11: error: No implicit Ordering defined for Person.
persons.min
^

scala> persons.minBy(p => p)
:11: error: No implicit Ordering defined for Person.
persons.minBy(p => p)
^

Let’s define an ordering by name:

scala> implicit object PersonOrdering extends Ordering[Person] {
| def compare(x: Person, y: Person): Int = x.name.compare(y.name)
| }
defined module PersonOrdering

scala> persons.min
res3: Person = Person(MidLifeCrisis,40)

scala> persons.max
res4: Person = Person(Young,17)

Now you have a reusable ordering for person which you can use for getting the min/max element or other things like sorting.

3 thoughts on “Using minBy and maxBy of Scala Collections API

  1. Pingback: Elasticsearch minBy « news-Knowlage FeeD

  2. Thank you. I was thinking that persons.maxBy(_.age) would give me the value of the max age, but now I see that persons.maxBy(_.age) returns the whole object Person = Person(Wise, 99) and if you are just interested in the max value, you do persons.max(_.age).age to get the value Int = 99.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s