Каков наилучший способ сделать обратный сортировку в scala? Я предполагаю, что следующее несколько медленнее.
list.sortBy(_.size).reverse
Есть ли удобный способ использования sortBy, но получить обратный вид? Я бы предпочел не использовать sortWith
.
Может быть очевидный способ изменения знака, если вы сортируете по некоторому числовому значению
list.sortBy(- _.size)
В более общем плане сортировка может выполняться методом, отсортированным с неявным порядком, который вы можете сделать явным, а Ordering имеет обратную ссылку (а не список ниже) Вы можете сделать
list.sorted(theOrdering.reverse)
Если упорядочение, которое вы хотите изменить, - это неявное упорядочение, вы можете получить его неявным образом [Заказ [A]] (A тип, который вы заказываете) или лучше Заказ [A]. Это будет
list.sorted(Ordering[TheType].reverse)
sortBy похож на Ordering.by, поэтому вы можете сделать
list.sorted(Ordering.by(_.size).reverse)
Возможно, не кратчайший для записи (по сравнению с минусом), но намерение четкое
Обновление
Последняя строка не работает. Чтобы принять _
в Ordering.by(_.size)
, компилятор должен знать, на каком типе мы заказываем, чтобы он мог ввести _
. Может показаться, что это будет тип элемента списка, но это не так, поскольку подпись сортировки
def sorted[B >: A](ordering: Ordering[B])
. Порядок может быть на A
, но также на любом предке A
(вы можете использовать byHashCode : Ordering[Any] = Ordering.by(_.hashCode)
). И действительно, тот факт, что список является ковариантным, заставляет эту подпись.
Можно делать
list.sorted(Ordering.by((_: TheType).size).reverse)
но это гораздо менее приятно.
list.sortBy(_.size)(Ordering[Int].reverse)
возможно, чтобы сократить его немного больше:
def Desc[T : Ordering] = implicitly[Ordering[T]].reverse
List("1","22","4444","333").sortBy( _.size )(Desc)
Легкий peasy (по крайней мере, в случае 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)
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)
Оба 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
легче понять.
Другая возможность в случаях, когда вы передаете функцию, которую вы не можете модифицировать непосредственно в 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()