【问题标题】:scala: How to sort Seq with an Ordering object?scala:如何使用 Ordering 对象对 Seq 进行排序?
【发布时间】:2014-01-09 22:32:26
【问题描述】:

来自 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。那么为什么上面会失败呢?

【问题讨论】:

    标签: scala


    【解决方案1】:

    Sorting 中,quickSort 实现是就地完成的,有一堆仅适用于数组的基于索引的移动(而Seq 根本没有定义索引) .

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

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

    stableSort 然而,有两种不同的形式。一个需要 Seq,另一个需要 Array。

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

    采用 Array 的形式还返回 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)
    

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

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

    【讨论】:

    • 一切都好 -- 但是为什么 stableSort 无法使用上面示例中提供的 Seq 进行编译?
    • @user48956 在帖子中包含 full 编译器消息,然后我们将看到一些答案解决该问题 ;-) 在这种情况下还要删除 quickSort 调用根本没有在 Seq 上定义。
    • 无法让 classTag/ClassTag 工作,但添加 mainfest[Person] 可以:stackoverflow.com/questions/2627919/…
    • @user48956 标签更新(在 Scala 2.10 中);你的目标是哪个版本?无论如何,很高兴你解决了它!
    • 使用 2.10。缺少 classTag 的导入 - 这是从哪里来的? ClassTag (with import reflect.ClassTag) 抱怨参数不足。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    相关资源
    最近更新 更多