Scala에서 두 필드로 목록을 정렬하는 방법은 무엇입니까?


101

Scala에서 두 필드로 목록을 정렬하는 방법,이 예제에서는 lastName과 firstName으로 정렬 할 것입니다.

case class Row(var firstName: String, var lastName: String, var city: String)

var rows = List(new Row("Oscar", "Wilde", "London"),
                new Row("Otto",  "Swift", "Berlin"),
                new Row("Carl",  "Swift", "Paris"),
                new Row("Hans",  "Swift", "Dublin"),
                new Row("Hugo",  "Swift", "Sligo"))

rows.sortBy(_.lastName)

나는 이런 것을 시도한다

rows.sortBy(_.lastName + _.firstName)

하지만 작동하지 않습니다. 그래서 좋고 쉬운 해결책이 궁금합니다.

답변:


216
rows.sortBy(r => (r.lastName, r.firstName))

4
lastName에서 역순 정렬 한 다음 firstName에서 자연 정렬하려면 어떻게해야합니까?
Sachin K

14
@SachinK : 클래스 Ordering용으로 직접 생성 Row하고 다음과 sorted같은 방법으로 사용해야합니다 rows.sorted(customOrdering).. 다음 과 같이 custom Ordering을 사용할 수도 있습니다 . Tuple2rows.sortBy(r => (r.lastName, r.firstName))( Ordering.Tuple2(Ordering.String.reverse, Ordering.String) )
senia

5
@SachinK : 당신은 구현할 수 customOrderingOrdering[Row]수동 또는 사용 Ordering.by:이 같은 val customOrdering = Ordering.by ((R : 행) => (r.lastName, r.firstName)) (Ordering.Tuple2 (Ordering.String.reverse, Ordering.String)) `
senia 2014-06-18

1
우수한. 또는 내림차순 정렬rows.sortBy(r => (-r.field1, -r.field2))
Brent Faust

@BrentFaust -와 함께 사용할 수 없습니다 String. 당신은 사용해야하는 Ordering::reverse이 방법 : rows.sortBy(r => (r.lastName, r.firstName))(implicitly[Ordering[(String, String)]].reverse).
senia aug

12
rows.sortBy (row => row.lastName + row.firstName)

질문에서와 같이 병합 된 이름을 기준으로 정렬하려는 경우 또는

rows.sortBy (row => (row.lastName, row.firstName))

처음에 lastName으로 정렬하려면 firstName; 더 긴 이름과 관련이 있습니다 (Wild, Wilder, Wilderman).

쓰면

rows.sortBy(_.lastName + _.firstName)

2 개의 밑줄이있는 메서드는 두 개의 매개 변수를 예상합니다.

<console>:14: error: wrong number of parameters; expected = 1
       rows.sortBy (_.lastName + _.firstName)
                               ^

1
이 순서는 이름, 성 순으로 정렬하는 것과 같지 않을 것입니다.
Marcin

1
특히, 마지막 이름은 diffferent 길이는 경우
루이지 Plinge

7

일반적으로 안정적인 정렬 알고리즘을 사용하는 경우 하나의 키로 정렬 한 다음 다음 키로 정렬 할 수 있습니다.

rows.sortBy(_.firstName).sortBy(_.lastName)

최종 결과는 성을 기준으로 정렬 된 다음 동일한 경우 이름을 기준으로 정렬됩니다.


스칼라가 sortBy안정적인 정렬을 사용하고 있습니까? 그렇지 않으면이 대답은 의미가 없습니다.
om-nom-nom 2012

1
@ om-nom-nom : scala-lang.org/api/current/scala/util/Sorting$.html quickSort는 값 유형에 대해서만 정의되므로 그렇습니다.
Marcin

1
rows변경 불가능한 목록이며 sortBy작동하는 항목을 변경하지 않고 새 값을 반환합니다 (변경 가능한 클래스에서도 마찬가지 임). 따라서 두 번째 표현은 원래 정렬되지 않은 목록을 정렬하는 것입니다.
Luigi Plinge 2012

3
Scala는 sortBy 메서드의 내부에서 java.util.Arrays.sort를 사용하는데, 이는 객체 배열이 안정적임을 보장합니다. 네,이 솔루션이 맞습니다. (이것은 Scala 2.10에서 확인되었습니다)
Marcin Pieciukiewicz 2013-06-28

1
튜플을 생성하는 단일 sortBy 대 이것의 성능에 대해 생각하는 것은 흥미 롭습니다. 이 접근법을 사용하면 분명히 그러한 튜플을 만들 필요가 없지만 튜플 접근법을 사용하면 성이 일치하는 이름 만 비교하면됩니다. 하지만 중요하지 않다고 생각합니다. 성능이 중요한 코드를 작성하는 경우 sortBy를 전혀 사용하지 않아야합니다!
AmigoNico 2014 년

-3

아마도 이것은 튜플 목록에서만 작동하지만

scala> var zz = List((1, 0.1), (2, 0.5), (3, 0.6), (4, 0.3), (5, 0.1))
zz: List[(Int, Double)] = List((1,0.1), (2,0.5), (3,0.6), (4,0.3), (5,0.1))

scala> zz.sortBy( x => (-x._2, x._1))
res54: List[(Int, Double)] = List((3,0.6), (2,0.5), (4,0.3), (1,0.1), (5,0.1))

작동하는 것처럼 보이고 그것을 표현하는 간단한 방법입니다.


그러나 OP가 정렬하는 문자열에는 작동하지 않습니다.
The Archetypal Paul

이 질문에는 이미 튜플 목록에 국한되지 않는 몇 가지 잘 알려진 답변이 있습니다. 그래서 그것을 게시하는 이유는 무엇입니까?
울려

@honk : 이전 솔루션은 실제로 튜플 목록에서 작동하지 않습니다 (AFAICT). 내가 Scala 초보자가 아니었다면 아마도 그 경우에 작동하도록 이전 솔루션을 모핑하는 방법을 이해했을 것입니다.하지만 오늘은 그렇지 않습니다. 내 대답이 다른 스칼라 초보자가 내가하려는 것과 똑같은 일을하는 데 도움이 될 것이라고 생각했습니다.
spreinhardt 2014 년

@ user3508605 : 기여 해주신 여러분의 의지에 감사드립니다. 그러나 Stack Overflow의 아이디어는 특정 문제 (여기의 경우)에 대한 질문과 해당 특정 문제 (및 해당 문제 만)를 해결하는 답변을 갖는 것입니다. 귀하의 답변은 다른 문제에 대한 해결책을 제공합니다. 따라서 이것은 게시하기에 잘못된 장소입니다. 귀하의 답변이 가치 있다고 생각되면 새로운 질문을하십시오. 새 질문에 해당 문제를 설명하고 거기에 답변을 게시하십시오. 마지막으로 여기에서 답변을 제거하는 것을 잊지 마십시오. 협력 해주셔서 감사합니다!
울려

@honk : 물론입니다. 제 답변을 별도의 질문으로 옮길 것입니다. 그리고이 질문에 대한 이전 답변 (Marcin)에 대한 의견을 추가하도록 강요 할 수 있다면 그것은 잘못된 것 같습니다. (저는 그것에 게시 할 수있는 충분한 신뢰성 포인트가 없습니다.) 그 대답의 예는 먼저 하나의 키로 정렬 한 다음 다른 키로 다시 정렬하여 첫 번째 정렬의 결과를 효과적으로 제거합니다. 적어도 튜플 목록에서는 수행합니다.
spreinhardt 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.