Cách tốt nhất để sắp xếp ngược trong scala là gì?


137

Cách tốt nhất để làm một loại nghịch đảo trong scala là gì? Tôi tưởng tượng sau đây là hơi chậm.

list.sortBy(_.size).reverse

Có một cách sử dụng sortBy thuận tiện nhưng nhận được một loại ngược lại? Tôi thà không cần sử dụng sortWith.


1
tất cả các giải pháp dưới đây đều rất hay nhưng tôi vẫn thấy cách làm ban đầu của bạn đơn giản hơn để đọc. Tôi đã xác minh rằng có một nhược điểm tính toán cho cách viết này như bạn nghi ngờ. Bài kiểm tra tôi đã thực hiện như sau: val clock = new Timer (1 đến 1e6.toInt) .sort (Đặt hàng [Int] .reverse) clock.addLap ("cách chính xác") (1 đến 1e6.toInt) .sort.reverse clock.addLap ("không chính xác") println (clock.toString) [cách chính xác, lap = 76, dur. = 76] | [cách không chính xác, lap = 326, dur. = 250]
Khoa

Câu trả lời:


241

Có thể có cách rõ ràng để thay đổi dấu hiệu, nếu bạn sắp xếp theo một số giá trị số

list.sortBy(- _.size)

Tổng quát hơn, việc sắp xếp có thể được thực hiện bằng phương pháp được sắp xếp với một Thứ tự ngầm, mà bạn có thể làm rõ ràng và Đặt hàng có một đảo ngược (không phải là danh sách đảo ngược bên dưới) Bạn có thể làm

list.sorted(theOrdering.reverse)

Nếu thứ tự bạn muốn đảo ngược là thứ tự ngầm, bạn có thể nhận được nó bằng cách ngầm định [Đặt hàng [A]] (Loại bạn đang đặt hàng) hoặc Đặt hàng tốt hơn [A]. Đó sẽ là

list.sorted(Ordering[TheType].reverse)

sortBy giống như sử dụng Ordering.by, vì vậy bạn có thể làm

list.sorted(Ordering.by(_.size).reverse)

Có thể không phải là ngắn nhất để viết (so với trừ) nhưng ý định là rõ ràng

Cập nhật

Dòng cuối cùng không hoạt động. Để chấp nhận _in Ordering.by(_.size), trình biên dịch cần biết chúng ta đang sắp xếp loại nào, để nó có thể gõ _. Có vẻ như đó sẽ là loại phần tử của danh sách, nhưng điều này không phải như vậy, vì chữ ký được sắp xếp là def sorted[B >: A](ordering: Ordering[B]). Thứ tự có thể được bật A, nhưng cũng có thể trên bất kỳ tổ tiên nào A(bạn có thể sử dụng byHashCode : Ordering[Any] = Ordering.by(_.hashCode)). Và thực sự, thực tế danh sách đó là covariant buộc chữ ký này. Một người có thể làm

list.sorted(Ordering.by((_: TheType).size).reverse)

nhưng điều này là ít dễ chịu hơn nhiều.


Siêu hữu ích - Tôi không chắc là tôi có hỏi một câu hỏi ngớ ngẩn không, nhưng tôi đã học được rất nhiều từ câu trả lời của bạn!
schmmd

Ngoại trừ việc nó không hoạt động. Tôi không bao giờ nên trả lời khi tôi không có REPL tiện dụng. Xem cập nhật.
Didier Dupont

Và để sắp xếp trên một trường thứ cấp, hãy trả lại một tuple:list.sortBy(x => (-x.size, x.forTiesUseThisField))
Brent Faust

2
Thay vì list.sorted(Ordering.by((_: TheType).size).reverse)xem xét list.sorted(Ordering.by[TheType, Int](_.size).reverse)nó rõ ràng hơn (nhưng lâu hơn) cho quan điểm của tôi về veiw.
Cherry

5
Cá nhân tôi list.sortBy(_.size)(Ordering[Int].reverse)cũng thích .
dtech


27

có lẽ để rút ngắn nó thêm một chút:

def Desc[T : Ordering] = implicitly[Ordering[T]].reverse

List("1","22","4444","333").sortBy( _.size )(Desc)

19

Dễ dàng dễ dàng (ít nhất là trong trường hợp size):

scala> val list = List("abc","a","abcde")
list: List[java.lang.String] = List(abc, a, abcde)

scala> list.sortBy(-_.size)
res0: List[java.lang.String] = List(abcde, abc, a)

scala> list.sortBy(_.size)
res1: List[java.lang.String] = List(a, abc, abcde)

9

sortBycó tham số ngầm ordcung cấp thứ tự

def sortBy [B] (f: (A) ⇒ B)(implicit ord: Ordering[B]): List[A]

vì vậy, chúng ta có thể định nghĩa Orderingđối tượng riêng

scala> implicit object Comp extends Ordering[Int] {
 | override def compare (x: Int, y: Int): Int = y - x
 | }
defined module Comp

List(3,2,5,1,6).sortBy(x => x)
res5: List[Int] = List(6, 5, 3, 2, 1)

9

Cả hai sortWithsortBycó một cú pháp nhỏ gọn:

case class Foo(time:Long, str:String)

val l = List(Foo(1, "hi"), Foo(2, "a"), Foo(3, "X"))

l.sortWith(_.time > _.time)  // List(Foo(3,X), Foo(2,a), Foo(1,hi))

l.sortBy(- _.time)           // List(Foo(3,X), Foo(2,a), Foo(1,hi))

l.sortBy(_.time)             // List(Foo(1,hi), Foo(2,a), Foo(3,X))

Tôi tìm thấy một trong những sortWithdễ hiểu hơn.


8
val list = List(2, 5, 3, 1)
list.sortWith(_>_) -> res14: List[Int] = List(5, 3, 2, 1)
list.sortWith(_<_) -> res14: List[Int] = List(1, 2, 3, 5)

Không giải quyết câu hỏi.
dấu ngã

1

Một khả năng khác trong trường hợp bạn truyền một hàm mà bạn không thể sửa đổi trực tiếp thành Arraybuffer thông qua sortWith chẳng hạn:

val buf = collection.mutable.ArrayBuffer[Int]()
buf += 3
buf += 9
buf += 1

// the sort function (may be passed through from elsewhere)
def sortFn = (A:Int, B:Int) => { A < B }

// the two ways to sort below
buf.sortWith(sortFn)                        // 1, 3, 9
buf.sortWith((A,B) => { ! sortFn(A,B) })    // 9, 3, 1

0

đây là mã của tôi;)

val wordCounts = logData.flatMap(line => line.split(" "))
                        .map(word => (word, 1))
                        .reduceByKey((a, b) => a + b)

wordCounts.sortBy(- _._2).collect()

1
Điều này không phải là không chính xác, nhưng phần thú vị (dòng thứ hai) bị nhấn chìm bởi dòng không cần thiết trước nó. Về cơ bản, vấn đề ở đây là một cách để thực hiện sắp xếp ngược lại là phủ định giá trị sắp xếp.
Carl-Eric Menzel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.