Scala에서 배열을 어떻게 정렬합니까?


81

나는 정렬 개체가, 거기에 볼 수 Sorting하는와 퀵의 방법, quickSort그 위에.

임의 유형의 객체 배열을 정렬하여 사용하는 코드 예제는 무엇입니까? Orderable특성 구현을 전달해야하는 것 같지만 구문이 확실하지 않습니다.

또한 'Scala 방식'으로 답변하는 것을 선호합니다. 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

편집을 참조하십시오. 당신도 확장 내 예처럼 사용하거나 혼합 된 인 "MyClass 클래스는 정렬 된 [MyClass에]와 OtherClass을 확장합니다."
skaffman

감사. 후자를 할 것 같아요.
Dan Gravell

6
현학적이지는 않지만 ... 클래스가 Ordered를 확장 할 필요는 없습니다. 클래스에서 Ordered를 확장하는 것으로 범위에 뷰 (암시 적 변환이라고도 함)가 있으면 충분합니다.
Kim Stebel

100

Scala 2.8 이상에서는 다음을 수행 할 수 있습니다.

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

그것은 quicksort의 구현 인 java.util.Arrays.sort 를 사용합니다 .


2
암시 적 순서를 사용하여, 심지어 짧은 : 목록 (3,7,5,2)에 따라 .sorted scala.collection.immutable.LinearSeq
Utgarda

sortWith가 java.util.Arrays.sort를 사용하고 있는지 어떻게 알 수 있습니까? 그것에 대한 참조가 있습니까?
deepkimo 2014 년


이것은 원래 질문이 묻는 것과 약간 다릅니다. 그것은 확실히 새로운 정렬 된 목록 (또는 원래 질문에 제시된 배열)을 만드는 데 작동하지만 sortWith는 원래 목록 또는 배열을 제자리에 정렬하는 것과는 반대로 새 개체를 반환합니다.
rphutchinson 2014 년

57

요즘 이것도 작동합니다.

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


그리고 역순으로 정렬한다고 가정합니다. 관용적 인 방법은 List(3,7,5,2).sorted.reverse?
Nick Chammas

19

정렬 만하고 싶지만 특히 Sorting 개체와 연결되어 있지 않은 경우 List의 정렬 방법을 사용할 수 있습니다. 비교 함수를 인수로 사용하므로 원하는 유형에 사용할 수 있습니다.

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

List(1, 4, 3, 2).sort((e1, e2) => (e1 < e2))

목록은 배열보다 "더 많은 스칼라"로 분류 될 수 있습니다.

스칼라 API 문서에서 :

def sort (lt : (A, A) => Boolean) : 목록 [A]

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

e1이 e2보다 작은 경우 true 여야하는 부울입니다.


음, List에는 정렬 방법이 있지만 Array에는 없습니다. 얼마나 불만족스럽게 불규칙한가. Java API에서 그런 종류의 말도 안되는 소리를 기대하지만 Scala는 아닙니다.
skaffman

나는 확실히 알기에는 너무 많은 scala newb이지만 Scala가 모든 자바 항목과의 호환성을 유지하고 있다는 점을 감안할 때 필요한 악할 수 있습니다. 반면에 스칼라는 마법을 너무 많이해서 더 많은 일을하기를 원할 정도로 정상인 것 같습니다!
Peter Recore

5
List (...) sort {_ <_} 더 관용적입니다.
Daniel Spiewak

2
"다니엘"< "크리스"== 거짓 : 그것은 또한 문자열 (암시 적 변환을 통해)의 <방법 정의 않는다는 것을 주목할 필요가
다니엘 스피 웍

11
그냥 정보를 원하시면, 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

3

받아 들여지는 대답은 틀리지 않지만 quicksort 방법은 그보다 더 많은 유연성을 제공합니다. 이 예제를 작성했습니다.

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.