【问题标题】:How do I sort an array in Scala?如何在 Scala 中对数组进行排序?
【发布时间】:2010-11-11 01:00:25
【问题描述】:

我可以看到有一个排序对象Sorting,上面有一个quicksort 方法quickSort。

什么是使用它的代码示例,对任意类型的对象数组进行排序?看起来我需要传入 Orderable 特征的实现,但我不确定语法。

另外,我更喜欢“Scala 方式”的答案。我知道我可以只使用 Java 库。

【问题讨论】:

    标签: sorting scala


    【解决方案1】:

    使用 Scala 2.8 或更高版本可以:

    List(3,7,5,2).sortWith(_ < _)
    

    使用java.util.Arrays.sort,一种快速排序的实现。

    【讨论】:

    【解决方案2】:

    现在这个也有效:

    List(3,7,5,2).sorted

    【讨论】:

    • 我想反向排序,惯用的方式是List(3,7,5,2).sorted.reverse?
    【解决方案3】:

    Sorting.quickSort 声明了用于获取数字或字符串数​​组的函数,但我假设您的意思是您想要对自己类的对象列表进行排序?

    我认为您正在查看的功能是

    quickSort [K](a : Array[K])(implicit view$1 : (K) => Ordered[K]) : Unit
    

    如果我没看错,这意味着 Array 中的对象必须具有 Ordered 特征。所以你的类必须扩展Ordered(或必须混合),因此必须实现该特征的compare方法。

    所以从书中抄袭一个例子:

    class MyClass(n: Int) extends Ordered[MyClass] {
       ...
      def compare(that: MyClass) =
        this.n - that.n
    }
    

    所以给定一个 Array[MyClass],Sorting.quickSort 应该可以工作。

    【讨论】:

    • 是的,就是这个。现在你指出它是有道理的。我将如何“混入”?
    • 查看编辑。您可以像我的示例一样扩展,或者使用“class MyClass extends OtherClass with Ordered[MyClass]”,这是一种混合。
    • 谢谢。我想我会做后者。
    • 不要迂腐,但是......你的类不需要扩展 Ordered,在你的类的范围内有一个视图(也称为隐式转换)就足够了已订购。
    【解决方案4】:

    如果您只想对事物进行排序,但又不特别与 Sorting 对象结合,则可以使用 List 的 sort 方法。它接受一个比较函数作为参数,所以你可以在任何你喜欢的类型上使用它:

    List("Steve", "Tom", "John", "Bob").sort((e1, e2) => (e1 compareTo e2) < 0)
    
    List(1, 4, 3, 2).sort((e1, e2) => (e1 < e2))
    

    列表可能比数组更“可缩放”。

    来自 scala api docs:

    def sort(lt : (A, A) => Boolean) : 列表[A]

    Sort the list according to the comparison function <(e1: a, e2: a) =>
    

    布尔值,如果 e1 应该为真 小于 e2。

    【讨论】:

    • 嗯,所以 List 有一个排序方法,但 Array 没有。多么令人不满意的不规则。我希望 Java API 会出现这种废话,但 Scala 不会。
    • 我是一个 Scala 新手,无法确定,但考虑到 Scala 保持与所有 java 内容的兼容性,这可能是必要的邪恶。另一方面,Scala 做了这么多魔法,想要它做得更多似乎很正常!
    • List(...) sort { _
    • 还值得注意的是,String 确实(通过隐式转换)定义了
    • 仅供参考,在 scala 2.9.1 上排序似乎已弃用,请使用 sortWith
    【解决方案5】:
    val array = Array((for(i <- 0 to 10) yield scala.util.Random.nextInt): _*)
    scala.util.Sorting.quickSort(array)
    

    Scala 的“默认”数组是可变数据结构,非常接近 Java 的数组。一般来说,这意味着“数组”不是非常 Scala-ish,即使是可变数据结构也是如此。不过,它是有目的的。如果数组是您需要的正确数据类型,那么这就是您对其进行排序的方式。顺便说一下,对象排序还有其他排序方法。

    我想我刚刚意识到你的问题是什么......你不需要传递任何隐式参数(毕竟它是隐式的)。该参数的存在表示必须有某种方法将类型 K 转换为 Ordered[K]。 Scala 的类已经存在这些定义,因此您不需要它们。

    对于任意类,您可以这样定义:

    scala> case class Person(name: String)
    defined class Person
    
    scala> val array = Array(Person("John"), Person("Mike"), Person("Abe"))
    array: Array[Person] = Array(Person(John), Person(Mike), Person(Abe))
    
    scala> scala.util.Sorting.quickSort(array)
    <console>:11: error: no implicit argument matching parameter type (Person) => Ordered[Person] was found.
           scala.util.Sorting.quickSort(array)
                                       ^
    scala> class OrderedPerson(val person: Person) extends Ordered[Person] {
         | def compare(that: Person) = person.name.compare(that.name)
         | }
    defined class OrderedPerson
    
    scala> implicit def personToOrdered(p: Person) = new OrderedPerson(p)
    personToOrdered: (p: Person)OrderedPerson
    
    scala> scala.util.Sorting.quickSort(array)
    
    scala> array
    res8: Array[Person] = Array(Person(Abe), Person(John), Person(Mike))
    

    现在,如果 Person 一开始就被命令,这将不是问题:

    scala> case class Person(name: String) extends Ordered[Person] {
         | def compare(that: Person) = name.compare(that.name)
         | }
    defined class Person
    
    scala> val array = Array(Person("John"), Person("Mike"), Person("Abe"))
    array: Array[Person] = Array(Person(John), Person(Mike), Person(Abe))
    
    scala>  scala.util.Sorting.quickSort(array)
    
    scala> array
    res10: Array[Person] = Array(Person(Abe), Person(John), Person(Mike))
    

    【讨论】:

    • 抱歉,我不清楚:我需要对任意类型的对象数组进行排序,而不是数字。
    【解决方案6】:

    虽然接受的答案没有错,但快速排序方法提供了更多的灵活性。我为你写了这个例子。

    import System.out.println
    import scala.util.Sorting.quickSort
    
    class Foo(x:Int) {
    def get = x
    }
    
    //a wrapper around Foo that implements Ordered[Foo]
    class OrdFoo(x:Foo) extends Ordered[Foo] {
    def compare(that:Foo) = x.get-that.get
    }
    //another wrapper around Foo that implements Ordered[Foo] in a different way
    class OrdFoo2(x:Foo) extends Ordered[Foo] {
    def compare(that:Foo) = that.get-x.get
    }
    //an implicit conversion from Foo to OrdFoo
    implicit def convert(a:Foo) = new OrdFoo(a)
    
    //an array of Foos
    val arr = Array(new Foo(2),new Foo(3),new Foo(1))
    
    //sorting using OrdFoo
    scala.util.Sorting.quickSort(arr)
    arr foreach (a=>println(a.get))
    /*
    This will print:
    1
    2
    3
    */
    
    //sorting using OrdFoo2
    scala.util.Sorting.quickSort(arr)(new OrdFoo2(_))
    arr foreach (a=>println(a.get))
    /*
    This will print:
    3
    2
    1
    */
    

    这显示了如何使用从 Foo 到扩展 Ordered[Foo] 的某个类的隐式和显式转换来获得不同的排序顺序。

    【讨论】:

      【解决方案7】:

      我更喜欢用户 Sorting util

      例子:

      val arr = Array(7,5,1, 9,2)
      
      scala.util.Sorting.quickSort(arr)
      

      请阅读本文以获取更多信息Sorting util

      【讨论】:

      • 为什么要链接到旧的 2.9.0 API 文档而不是 current docs?
      猜你喜欢
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 2014-07-13
      • 2011-11-18
      • 2012-11-20
      • 2015-04-12
      相关资源
      最近更新 更多