在 scala 中进行逆排序的最佳方法是什么。
list.sortBy(_.size).reverse
有没有使用 sortBy 但得到反向排序的简便方法?我宁愿不需要使用 sortWith。
sortWith
sortBy有提供排序的隐式参数 ord
sortBy
ord
def sortBy [B] (f: (A) ⇒ B)(implicit ord: Ordering[B]): List[A]
因此,我们可以定义自己的 Ordering对象
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的情况下) :
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) 你可以的
reverse
list.sorted(theOrdering.reverse)
如果您想要反转的顺序是隐式顺序,您可以通过 implicitly[Ordering[A]](A类型,您正在订购)或更好的 Ordering[A]得到它。应该是
implicitly[Ordering[A]]
A
Ordering[A]
list.sorted(Ordering[TheType].reverse)
sortBy就像使用 Ordering.by一样,所以你可以这样做
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))。事实上,列表是协变的这一事实迫使这种签名。 一个人可以做到
Ordering.by(_.size)
_
def sorted[B >: A](ordering: Ordering[B])
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)
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的那个更容易理解。
这是我的密码;)
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)