2014-09-24 1 views
2

Учитывая, что у меня есть два Seq[M] и функция-компаратор как функция compare(m1:M, m2:M):Int, как бы я написал функцию сравнения для двух последовательностей.scala компаратор как функция для последовательностей

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

Я не буду никаких проблем, чтобы реализовать это сама итерацию последовательности, но я уверен, что есть что-то в готовом виде в библиотеке Scala уже. Я смотрю на класс и объект Ordering, но у меня есть проблемы, чтобы увидеть лес для всех неявных деревьев.

EDIT: Любой способ использования seqDerivedOrdering, который можно увидеть в https://github.com/scala/scala/blob/v2.11.2/src/library/scala/math/Ordering.scala#L1, кроме копирования кода?

ответ

3

Вы можете использовать seqDerivedOrdering, но вы все равно должны предоставить неявный заказ, так как он не принимает (M,M) => Int. Вы могли бы попробовать что-то вроде этого:

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) 
    } 

и, возможно, немного лучше версии одного и того же кода:

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) 
    } 

Или, мы можем сделать еще лучше:

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) 
    } 
+0

После прочтения Http: //docs.scala-lang.org/tutorials/tour/implicit-parameters.html, последний начал иметь смысл для меня. Увы, заказ больше не нужен. По крайней мере, он работает для List [Int] и List [String] без. -) И тогда это действительно хорошо и просто. – Harald

+0

Uuhm, о, теперь я понял. Без orderM мой cmp никогда не используется. – Harald

1

По-моему, ничего не построено. Самый компактный, вероятно, что-то вроде

def compare[M](s1: Seq[M], s2: Seq[M], cmp: (M, M) => Int): Int = { 
    val diff = (s1 zip s2).find(x => cmp(x._1, x._2) != 0) 
    diff.map(x => cmp(x._1, x._2)).getOrElse(s1.length compare s2.length) 
} 

Решение с итераторами более эффективно, но менее компактно.

 Смежные вопросы

  • Нет связанных вопросов^_^