Skala'da ters sıralama yapmanın en iyi yolu nedir?


137

Skala'da ters sıralama yapmanın en iyi yolu nedir? Aşağıdakilerin biraz yavaş olduğunu hayal ediyorum.

list.sortBy(_.size).reverse

SortBy'yi kullanmanın ancak ters sıralama elde etmenin uygun bir yolu var mı? Kullanmayı tercih etmem sortWith.


1
Aşağıdaki çözümlerin hepsi çok güzel ama yine de bunu daha basit okumak için orijinal yolunuzu buluyorum. Şüphelendiğiniz gibi bu yazım biçiminde bir hesaplama dezavantajı olduğunu doğruladım. Yaptığım test şöyle: val clock = yeni Zamanlayıcı (1 ila 1e6.toInt) .sorted (Sipariş [Int] .reverse) clock.addLap ("doğru yol") (1 ila 1e6.toInt) .sorted.reverse clock.addLap ("yanlış yol") println (clock.toString) [doğru yol, tur = 76, dur. = 76] | [yanlış yol, tur = 326, dur. = 250]
Khoa

Yanıtlar:


242

Bazı sayısal değerlere göre sıralıyorsanız, işareti değiştirmenin açık bir yolu olabilir.

list.sortBy(- _.size)

Daha genel olarak, sıralama, açık bir şekilde yapabileceğiniz örtük bir Sıralama ile sıralanan yöntemle yapılabilir ve Sıralama'nın bir tersi vardır (aşağıdaki liste tersi değil)

list.sorted(theOrdering.reverse)

Tersine çevirmek istediğiniz siparişin üstü kapalı sipariş ise, bunu [Sipariş [A]] (Sipariş ettiğiniz tip A) veya daha iyi Sipariş [A] ile elde edebilirsiniz. Olurdu

list.sorted(Ordering[TheType].reverse)

sortBy, Ordering.by'yi kullanmak gibidir, böylece

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

Belki yazmak için en kısa değil (eksi ile karşılaştırıldığında) ama niyet açıktır

Güncelleme

Son satır çalışmıyor. Kabul etmek _in Ordering.by(_.size)biz sipariş Hangi tipe üzerinde, derleyici ihtiyacı o yazabilirsiniz böylece, bilmek _. Bu, listenin elemanının türü gibi görünebilir, ancak sıralanan imzanın olduğu gibi, bu böyle değildir def sorted[B >: A](ordering: Ordering[B]). Sıralama açık olabilir A, aynı zamanda herhangi bir atasına da A(kullanabilirsiniz byHashCode : Ordering[Any] = Ordering.by(_.hashCode)). Ve aslında, listenin kovaryant olması bu imzayı zorlar. Biri yapabilir

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

ama bu çok daha az hoş.


Süper yararlı - Aptalca bir soru sorduğumdan emin değildim, ama cevabından çok şey öğrendim!
schmmd

Dışında çalışmıyor. Hiçbir REPL kullanışlı olmadığında asla cevap vermemeliyim. Güncellemeye bakın.
Didier Dupont

Ve ikincil bir alanda sıralamak için bir demet döndürün:list.sortBy(x => (-x.size, x.forTiesUseThisField))
Brent Faust

2
Yerine list.sorted(Ordering.by((_: TheType).size).reverse)düşünün list.sorted(Ordering.by[TheType, Int](_.size).reverse)daha anlaşılır (ama daha uzun) veiw benim açımdan için.
Kiraz

5
Ben şahsen de severim list.sortBy(_.size)(Ordering[Int].reverse).
dtech


27

belki biraz daha kısaltmak için:

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

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

19

Kolay peasy (en azından durumunda 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

sortByordsipariş sağlayan örtük parametresi vardır

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

kendi Orderingnesnesini tanımlayabiliriz

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

Hem sortWithve sortBykompakt bir sözdizimi vardır:

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

sortWithAnlaması kolay olanı buluyorum .


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)

Soruyu ele almıyor.
tilde

1

Bir Arraybuffer'da sortWith ile doğrudan değiştiremeyebileceğiniz bir işlevi geçirdiğiniz durumlarda başka bir olasılık:

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

bu benim kodum;)

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

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

1
Bu yanlış değil, ama ilginç kısım (ikinci çizgi), önce gereksiz olan çizgi tarafından boğuluyor. Temel olarak, buradaki nokta, ters sıralama yapmanın bir yolunun sıralama değerini reddetmektir.
Carl-Eric Menzel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.