Apa cara terbaik untuk mengurutkan terbalik dalam skala?


142

Apa cara terbaik untuk melakukan pengurutan terbalik dalam skala? Saya membayangkan berikut ini agak lambat.

list.sortBy(_.size).reverse

Apakah ada cara yang mudah untuk menggunakan sortBy tetapi mendapatkan pengurutan terbalik? Saya lebih suka tidak perlu menggunakan sortWith.


1
solusi di bawah ini semuanya sangat bagus tetapi saya masih menemukan cara asli Anda untuk melakukan ini lebih sederhana untuk dibaca. Saya telah memverifikasi bahwa ada kekurangan komputasi pada cara penulisan ini seperti yang Anda duga. Tes yang saya lakukan adalah seperti ini: val clock = new Timer (1 to 1e6.toInt) .sorted (Ordering [Int] .reverse) clock.addLap ("cara yang benar") (1 to 1e6.toInt) .sorted.reverse clock.addLap ("salah cara") println (clock.toString) [cara yang benar, putaran = 76, dur. = 76] | [cara yang salah, putaran = 326, dur. = 250]
Khoa

Jawaban:


247

Mungkin ada cara yang jelas untuk mengubah tanda, jika Anda mengurutkan berdasarkan beberapa nilai numerik

list.sortBy(- _.size)

Secara lebih umum, pengurutan dapat dilakukan dengan metode yang diurutkan dengan Pengurutan implisit, yang dapat Anda buat secara eksplisit, dan Pengurutan memiliki kebalikan (bukan daftar terbalik di bawah). Anda dapat melakukannya

list.sorted(theOrdering.reverse)

Jika pengurutan yang ingin Anda balikkan adalah pengurutan implisit, Anda bisa mendapatkannya dengan [Pengurutan [A]] secara implisit (A tipe tempat Anda memesan) atau Pengurutan [A] yang lebih baik. Itu akan menjadi

list.sorted(Ordering[TheType].reverse)

sortBy seperti menggunakan Ordering.by, jadi Anda bisa melakukannya

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

Mungkin bukan yang terpendek untuk menulis (dibandingkan dengan minus) tetapi tujuannya jelas

Memperbarui

Baris terakhir tidak berfungsi. Untuk menerima _in Ordering.by(_.size), kompilator perlu mengetahui tipe mana yang kita pesan, sehingga ia dapat mengetik _. Tampaknya itu akan menjadi jenis elemen daftar, tetapi tidak demikian, karena tanda tangan diurutkan def sorted[B >: A](ordering: Ordering[B]). Pengurutan mungkin aktif A, tetapi juga pada leluhur mana pun A(Anda mungkin menggunakan byHashCode : Ordering[Any] = Ordering.by(_.hashCode)). Dan memang, fakta bahwa daftar adalah kovarian memaksa tanda tangan ini. Bisa dilakukan

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

tapi ini jauh lebih tidak menyenangkan.


Sangat membantu - Saya tidak yakin apakah saya mengajukan pertanyaan bodoh, tetapi saya belajar banyak dari jawaban Anda!
schmmd

Kecuali itu tidak berhasil. Saya seharusnya tidak menjawab ketika saya tidak memiliki REPL yang berguna. Lihat pembaruan.
Didier Dupont

Dan untuk mengurutkan bidang sekunder, kembalikan tupel:list.sortBy(x => (-x.size, x.forTiesUseThisField))
Brent Faust

2
Alih-alih list.sorted(Ordering.by((_: TheType).size).reverse)menganggapnya list.sorted(Ordering.by[TheType, Int](_.size).reverse)lebih jelas (tetapi lebih lama) untuk poin pandangan saya.
Cherry

5
Saya pribadi list.sortBy(_.size)(Ordering[Int].reverse)juga suka .
dtech


27

mungkin untuk mempersingkatnya sedikit:

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

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

19

Mudah sekali (setidaknya dalam kasus 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)

10

Keduanya sortWithdan sortBymemiliki sintaks yang ringkas:

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))

Saya menemukan yang sortWithlebih mudah dimengerti.


9

sortBymemiliki parameter implisit ordyang menyediakan pengurutan

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

jadi, kita bisa mendefinisikan Orderingobjeknya sendiri

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
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)

Tidak menjawab pertanyaan itu.
tilde

1

Kemungkinan lain dalam kasus di mana Anda meneruskan fungsi yang mungkin tidak dapat Anda ubah secara langsung ke Arraybuffer melalui sortWith misalnya:

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

ini kode saya;)

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

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

1
Ini tidak salah, tetapi bagian yang menarik (baris kedua) tenggelam oleh baris yang tidak dibutuhkan sebelumnya. Pada dasarnya, poin di sini adalah bahwa salah satu cara untuk melakukan pengurutan terbalik adalah dengan meniadakan nilai pengurutan.
Carl-Eric Menzel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.