在 Scala 中进行逆排序的最好方法是什么?

在 scala 中进行逆排序的最佳方法是什么。

list.sortBy(_.size).reverse

有没有使用 sortBy 但得到反向排序的简便方法?我宁愿不需要使用 sortWith

92891 次浏览

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)

小菜一碟(至少在 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)

如果按某个数值排序,可能有一种显而易见的方法来更改符号

list.sortBy(- _.size)

更一般地说,排序可以通过使用隐式 Ordering进行排序的方法来完成,您可以使用显式 Ordering,并且 Ordering有一个 reverse(而不是下面的列表 reverse) 你可以的

list.sorted(theOrdering.reverse)

如果您想要反转的顺序是隐式顺序,您可以通过 implicitly[Ordering[A]](A类型,您正在订购)或更好的 Ordering[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)

另一种可能性是,当你传递一个函数时,你可能无法通过 sortWith 直接修改到 Arraybuffer。例如:

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

sortWithsortBy都有一个紧凑的语法:

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的那个更容易理解。

这是我的密码;)

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


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

如果你想要一个泛型方法,你可以在 Scala 3中使用它;

extension [T, A: Ordering](a: List[T])
def sortByDesc(f: T => A) = a.sortBy(f)(Ordering[A].reverse)