score:30

C'mon guys, you made the poor questioner find "on" himself. Pretty shabby performance. You could shave a little further writing it like this:

``````list min Ordering[Int].on[(_,Int)](_._2)
``````

Which is still far too noisy but that's where we are at the moment.

score:3

You could always define your own implicit conversion:

``````implicit def funToOrdering[T,R <% Ordered[R]](f: T => R) = new Ordering[T] {
def compare(x: T, y: T) = f(x) compare f(y)
}

val list = ("a", 5) :: ("b", 3) :: ("c", 2) :: Nil

list.min { t: (String,Int) => t._2 }  // (c, 2)
``````

Might be more readable if the conversion wasn't implicit, but using an "on" function:

``````def on[T,R <% Ordered[R]](f: T => R) = new Ordering[T] {
def compare(x: T, y: T) = f(x) compare f(y)
}

val list = ("a", 5) :: ("b", 3) :: ("c", 2) :: Nil

list.min( on { t: (String,Int) => t._2 } ) // (c, 2)
``````

score:5

``````list.min(Ordering.fromLessThan[(String, Int)](_._2 < _._2))
``````

Which is still too verbose, of course. I'd probably declare it as a `val` or `object`.

score:8

The function `Ordering#on` witnesses the fact that `Ordering` is a contra-variant functor. Others include `Comparator`, `Function1`, `Comparable` and `scalaz.Equal`.

Scalaz provides a unified view on these types, so for any of them you can adapt the input with `value contramap f`, or with symbolic denotation, `value ∙ f`

``````scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> val ordering = implicitly[scala.Ordering[Int]] ∙ {x: (_, Int) => x._2}
ordering: scala.math.Ordering[Tuple2[_, Int]] = scala.math.Ordering\$\$anon\$2@34df289d

scala> List(("1", 1), ("2", 2)) min ordering
res2: (java.lang.String, Int) = (1,1)
``````

Here's the conversion from the `Ordering[Int]` to `Ordering[(_, Int)]` in more detail:

``````scala> scalaz.Scalaz.maContravariantImplicit[Ordering, Int](Ordering.Int).contramap { x: (_, Int) => x._2 }
res8: scala.math.Ordering[Tuple2[_, Int]] = scala.math.Ordering\$\$anon\$2@4fa666bf
``````

score:10

One thing you can do is use the more concise standard tuple type syntax instead of using `Tuple2`:

``````val min = list.min(new Ordering[(String, Int)] {
def compare(x: (String, Int), y: (String, Int)): Int = x._2 compare y._2
})
``````

Or use `reduceLeft` to have a more concise solution altogether:

``````val min = list.reduceLeft((a, b) => (if (a._2 < b._2) a else b))
``````

Or you could sort the list by your criterion and get the `first` element (or `last` for the max):

``````val min = list.sort( (a, b) => a._2 < b._2 ).first
``````

Which can be further shortened using the placeholder syntax:

``````val min = list.sort( _._2 < _._2 ).first
``````

Which, as you wrote yourself, can be shortened to:

``````val min = list.sortBy( _._2 ).first
``````

But as you suggested `sortBy` yourself, I'm not sure if you are looking for something different here.

score:40

In Scala 2.9, you can do `list minBy { _._2 }`.