scala:如何使用Ordering对象对Seq进行排序?

时间:2013-12-21 00:48:41

标签: scala

来自scala参考: http://www.scala-lang.org/files/archive/nightly/docs/library/index.html#scala.math.Ordering

  case class Person(name:String, age:Int)
  val people = Array(Person("bob", 30), Person("ann", 32), Person("carl", 19))

  // sort by age
  object AgeOrdering extends Ordering[Person] {
      def compare(a:Person, b:Person) = a.age compare b.age
  }

但是如果我想使用Ordering对象对Seq进行排序:

  // Want to sort a Seq, or event and IndexedSeq
  val ps = people.asInstanceOf[collection.Seq[Person]]

  // Type not enough arguments 
  // for method stableSort: (implicit evidence$6: scala.reflect.ClassTag[Person], 
  // implicit evidence$7: scala.math.Ordering[Person])Array[Person]. Unspecified value 
  // parameter evidence$7.  
  Sorting.stableSort(ps)(AgeOrdering)

编译器扼流圈。但是,stableSort API表示需要Seq。那么为什么上述失败呢?

1 个答案:

答案 0 :(得分:2)

Sorting中,quickSort实现是就地完成的,有一堆基于索引的移动,只适合在数组上完成(和Seq一样根本没有定义索引。)

quickSort[K](a: Array[K] ..): Unit

quickSort方法对输入执行副作用并返回Unit。

然而,stableSort两个不同的表单。采用Seq和采用数组的采样器。

stableSort[K](a: Seq[K] ..): Array[K]
stableSort[K](a: Array[K] ..): Unit

采用数组的表单也返回Unit并修改输入(作为quickSort但确保稳定性),而表单采用Seq返回一个新的Array对象(并且输入序列未被修改)。


错误是因为quickSort方法具有第二个参数组的签名:(implicit arg0: math.Ordering[K])stableSort方法具有:(implicit arg0: ClassTag[K], arg1: math.Ordering[K]) - 也就是说, 还需要ClassTag [K / Person]。

即使指定了顺序,也没有指定(或隐式解析)ClassTag[K]参数,Scala需要这个来创建内部使用的Array[Person](并返回)。由于Scala受到Java类型擦除的限制,该方法无法在没有其他帮助的情况下了解 类型K实际上是什么。

我不确定为什么它没有被隐含地解决(因为Scala暗示对我来说仍然是“神奇的”!),但明确传递相当容易:

val results = Sorting.stableSort(ps)(classTag[Person], AgeOrdering)

TypeTags and Manifests中讨论了TypeTag / ClassTag的一些理性和用法。

另见Scala: What is a TypeTag and how do I use it?