Search code examples
scalacomparatorseq

scala comparator like function for sequences


Given I have two Seq[M] and a comparator like function compare(m1:M, m2:M):Int, how would I write the comparator like function for the two sequences.

def compare[M](s1:Seq[M], s2:Seq[M], cmp:(M,M)=>Int) : Int = {
  ???
}

I would have no problem to implement this myself iterating over the sequences, but I am sure there is something ready made in the Scala library already. I look at the Ordering class and object but have problems to see the forest for all of the implicit trees.

EDIT: Any way to make use of seqDerivedOrdering that can be seen in https://github.com/scala/scala/blob/v2.11.2/src/library/scala/math/Ordering.scala#L1 other than copying the code?


Solution

  • You can use seqDerivedOrdering but you still have to provide an implicit ordering as it doesn't take (M,M) => Int. You could try something like this:

      def compare[M](s1: Seq[M], s2: Seq[M])(cmp: (M, M) => Int): Int = {
    
        implicit val orderM = new Ordering[M] {
          override def compare(x: M, y: M): Int = cmp(x, y)
        }
    
        scala.math.Ordering.Implicits.seqDerivedOrdering[Seq, M].compare(s1, s2)
      }
    

    And perhaps a slightly better version of the same code:

      def compare[M](s1: Seq[M], s2: Seq[M])(cmp: (M, M) => Int): Int = {
    
        import scala.math.Ordering.Implicits._
    
        implicit val orderM = new Ordering[M] {
          override def compare(x: M, y: M): Int = cmp(x, y)
        }
    
        implicitly[Ordering[Seq[M]]].compare(s1, s2)
      }
    

    Or, we can do even better:

      import scala.math.Ordering.Implicits._
    
      def compare[M](s1: Seq[M], s2: Seq[M])(cmp: (M, M) => Int)(implicit ord: Ordering[Seq[M]]): Int = {
    
        implicit val orderM = new Ordering[M] {
          override def compare(x: M, y: M): Int = cmp(x, y)
        }
    
        ord.compare(s1, s2)
      }