Как лучше всего выполнить обратную сортировку в scala? Я полагаю, что следующее происходит несколько медленно.
list.sortBy(_.size).reverse
Есть ли удобный способ использовать sortBy, но получить обратную сортировку? Я бы предпочел не использовать sortWith
.
Ответы:
Может быть очевидный способ изменить знак, если отсортировать по некоторому числовому значению
В более общем плане сортировка может выполняться методом, отсортированным с помощью неявного упорядочивания, которое вы можете сделать явным, а упорядочение имеет обратный порядок (не обратный список ниже).
Если порядок, который вы хотите изменить, является неявным порядком, вы можете получить его неявно [Порядок [A]] (A тип, который вы заказываете) или, лучше, Порядок [A]. Это было бы
list.sorted(Ordering[TheType].reverse)
sortBy похож на использование Ordering.by, поэтому вы можете
list.sorted(Ordering.by(_.size).reverse)
Может быть, не самый короткий для написания (по сравнению с минусом), но намерение ясное
Обновить
Последняя строчка не работает. Чтобы принять
_
inOrdering.by(_.size)
, компилятор должен знать, какой тип мы заказываем, чтобы он мог ввести_
. Может показаться, что это будет тип элемента списка, но это не так, как подпись sorteddef sorted[B >: A](ordering: Ordering[B])
. Упорядочивание может быть включеноA
, но также может быть любым предкомA
(вы можете использоватьbyHashCode : Ordering[Any] = Ordering.by(_.hashCode)
). И действительно, тот факт, что список ковариантен, заставляет эту подпись. Можно сделатьlist.sorted(Ordering.by((_: TheType).size).reverse)
но это гораздо менее приятно.
источник
list.sortBy(x => (-x.size, x.forTiesUseThisField))
list.sorted(Ordering.by((_: TheType).size).reverse)
считатьlist.sorted(Ordering.by[TheType, Int](_.size).reverse)
это более ясным (но более длинным) для моей точки зрения.list.sortBy(_.size)(Ordering[Int].reverse)
тоже нравится .list.sortBy(_.size)(Ordering[Int].reverse)
источник
возможно, чтобы сократить его еще немного:
def Desc[T : Ordering] = implicitly[Ordering[T]].reverse List("1","22","4444","333").sortBy( _.size )(Desc)
источник
Легко (по крайней мере, в случае
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)
источник
Оба
sortWith
иsortBy
имеют компактный синтаксис: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))
Я нахожу тот, который
sortWith
легче понять.источник
sortBy
имеет неявный параметр,ord
обеспечивающий порядокdef sortBy [B] (f: (A) ⇒ B)(implicit ord: Ordering[B]): List[A]
Итак, мы можем определить собственный
Ordering
объект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)
источник
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)
источник
Другая возможность в случаях, когда вы передаете функцию, которую вы не можете изменить напрямую в Arraybuffer через sortWith, например:
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
источник
это мой код;)
val wordCounts = logData.flatMap(line => line.split(" ")) .map(word => (word, 1)) .reduceByKey((a, b) => a + b) wordCounts.sortBy(- _._2).collect()
источник