我正在Scala中构建一些基本算法(遵循Cormen的书)以刷新我对该主题的想法,并且我正在构建插入排序算法。这样做,它可以正常工作:
class InsertionSort extends Sort {
def sort ( items : Array[Int] ) : Unit = {
if ( items.length < 2 ) {
throw new IllegalArgumentException( "Array must be bigger than 1" )
}
1.until( items.length ).foreach( ( currentIndex ) => {
val key = items(currentIndex)
var loopIndex = currentIndex - 1
while ( loopIndex > -1 && items(loopIndex) > key ) {
items.update( loopIndex + 1, items(loopIndex) )
loopIndex -= 1
}
items.update( loopIndex + 1, key )
} )
}
}
但这仅适用于 Int ,我想使用泛型和 Ordered [A] ,因此我可以对任何已订购的类型进行排序。当我将签名更改为:
def sort( items : Array[Ordered[_]] ) : Unit
以下规范无法编译:
"sort correctly with merge sort" in {
val items = Array[RichInt](5, 2, 4, 6, 1, 3)
insertionSort.sort( items )
items.toList === Array[RichInt]( 1, 2, 3, 4, 5, 6 ).toList
}
编译错误是:
Type mismatch, expected: Array[Ordered[_]], actual Array[RichInt]
但是RichInt是不是有序[RichInt]?我应该如何以接受任何Ordered对象的方式定义此方法签名?
修改
如果有人感兴趣,最终来源可用here。
答案 0 :(得分:10)
实际上RichInt
不是Ordered[RichInt]
而是Ordered[Int]
。但是scala.runtime.RichInt <: Ordered[_]
,但类Array
在T
类型中不变,因此Array[RichInt]
不是Array[Ordered[_]]
。
scala> def f[T <% Ordered[T]](arr: Array[T]) = { arr(0) < arr(1) }
f: [T](arr: Array[T])(implicit evidence$1: T => Ordered[T])Boolean
scala> f(Array(1,2,3))
res2: Boolean = true
scala>
答案 1 :(得分:6)
您可以在类型参数上使用context bound执行此操作;
scala> def foo[T : Ordering](arr: Array[T]) = {
| import math.Ordering.Implicits._
| arr(0) < arr(1)
| }
foo: [T](arr: Array[T])(implicit evidence$1: Ordering[T])Boolean
这样的用法是:
scala> foo(Array(2.3, 3.4))
res1: Boolean = true
这样做的好处是,如果您不需要,则不需要该类型的默认顺序:
scala> foo(Array("z", "bc"))
res4: Boolean = false
scala> foo(Array("z", "bc"))(Ordering.by(_.length))
res3: Boolean = true