Scalaで配列をソートするにはどうすればよいですか?


81

クイックソートメソッドがSorting付いた並べ替えオブジェクトがあります。quickSort

それを使用して、任意のタイプのオブジェクトの配列をソートするコード例は何でしょうか?Orderableトレイトの実装を渡す必要があるようですが、構文がわかりません。

また、私はこれを「スカラの方法」で行う答えを好みます。私はJavaライブラリを使用できることを知っています。

回答:


32

Sorting.quickSortは、数値または文字列の配列を取得するための関数を宣言していますが、独自のクラスのオブジェクトのリストを並べ替えたいという意味だと思いますか?

あなたが見ていると思う機能は

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

これは、私がこの権利を読んでいる場合、配列内のオブジェクトがOrdered特性を持っている必要があることを意味します。したがって、クラスを拡張するOrdered(または混合する)必要があるため、compare、その特性のメソッドをます。

それで、本から例を取り除くために:

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

したがって、Array [MyClass]が与えられると、Sorting.quickSortが機能するはずです。


ええ、それです。あなたがそれを指摘するのは理にかなっています。どのように「混ぜる」のですか?
Dan Gravell 2009

編集を参照してください。私の例のように拡張するか、「class MyClass extends OtherClass with Ordered [MyClass]」を使用します。これはミックスインです。
skaffman 2009

ありがとう。後者はやろうと思います。
Dan Gravell 2009

6
衒学的ではありませんが...クラスはOrderedを拡張する必要はありません。クラスから、Orderedを拡張するものへのスコープ内のビュー(暗黙の変換とも呼ばれます)があれば十分です。
Kim Stebel 2010

100

Scala 2.8以降では、次のことが可能です。

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

クイックソートの実装であるjava.util.Arrays.sortを使用します。


2
暗黙的な順序付けを使用して、さらに短くします:List(3,7,5,2).sorted per scala.collection.immutable.LinearSeq
Utgarda 2014年

sortWithがjava.util.Arrays.sortを使用していることをどのようにして知ることができますか?そのための参照はありますか?
deepkimo 2014年

ソースコードの@ deepkimogithub.com
scala /

これは、元の質問が尋ねていたものとは少し異なります。確かに、新しいソート済みリスト(または元の質問で提示された配列)を作成するために機能しますが、sortWithは、元のリストまたは配列を所定の場所でソートするのではなく、新しいオブジェクトを返します。
rphutchinson 2014年


19

物事を並べ替えるだけで、特に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ドキュメントから

def sort(lt:(A、A)=>ブール値):List [A]

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

ブール値。e1がe2よりも小さい場合はtrueになります。


うーん、Listにはsortメソッドがありますが、Arrayにはありません。どのように不満足に不規則です。私はJavaAPIにそのようなナンセンスを期待していますが、Scalaには期待していません。
skaffman 2009

私は確かに知るにはあまりにも多くのscala初心者ですが、ScalaがすべてのJavaのものとの互換性を維持していることを考えると、それは必要悪かもしれません。一方、Scalaは非常に多くの魔法を実行するので、さらに多くのことを実行したいのは正常なようです。
Peter Recore

5
List(...)sort {_ <_}はもっと慣用的です。
Daniel Spiewak 2009

2
Stringが(暗黙の変換を通じて)<メソッドを定義していることにも注意してください: "daniel" <"chris" == false
Daniel Spiewak 2009

11
ただ、情報のため、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の配列に非常に近いものです。一般的に言って、これは、可変データ構造が使用されている場合でも、「配列」はそれほどスカラっぽくないことを意味します。しかし、それは目的を果たします。配列がニーズに適したデータ型である場合は、それがソート方法です。ちなみに、オブジェクトの並べ替えには他の並べ替え方法があります。

私はあなたの質問が何であるかを理解したと思います...暗黙のパラメータを渡す必要はありません(結局のところ、暗黙のパラメータです)。そのパラメータは、タイプ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))

申し訳ありませんが、はっきりしていませんでした。数値ではなく、任意のタイプのオブジェクトの配列を並べ替える必要があります。
Dan Gravell 2009

3

受け入れられた答えは間違っていませんが、クイックソート方式はそれよりも柔軟性があります。私はあなたのためにこの例を書きました。

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]を拡張するクラスへの暗黙的および明示的な変換を使用して、さまざまな並べ替え順序を取得する方法を示しています。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.