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


137

在scala中进行逆排序的最佳方法是什么?我认为以下情况有些慢。

list.sortBy(_.size).reverse

有使用consortBy但获得反向排序的简便方法吗?我宁愿不需要使用sortWith


1
下面的解决方案都很好,但是我仍然找到您的原始方法来简化阅读。我已经证实,您怀疑这种书写方式存在计算缺陷。我所做的测试是这样的:val clock = new Timer(1 to 1e6.toInt).sorted(Ordering [Int] .reverse)clock.addLap(“ correct way”)(1 to 1e6.toInt).sorted.reverse clock.addLap(“ invalid way”)println(clock.toString)[正确方法,lap = 76,dur。= 76] | [错误的方式,单圈= 326,dur。= 250]
Khoa

Answers:


241

如果您按某个数值排序,则可能会有明显的方式来更改符号

list.sortBy(- _.size)

更一般而言,排序可以通过使用隐式Ordering排序的方法来完成,您可以将其显式地进行排序,并且Ordering具有相反的功能(而不是下面的列表相反的功能)

list.sorted(theOrdering.reverse)

如果要反转的顺序是隐式顺序,则可以通过隐式[Ordering [A]](要订购的类型)或更好的Ordering [A]来获得。那会是

list.sorted(Ordering[TheType].reverse)

sortBy就像使用Ordering.by,因此您可以

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

也许不是最短的写法(与减法相比),但意图很明确

更新资料

最后一行不起作用。要接受_in Ordering.by(_.size),编译器需要知道我们要订购的类型,以便它可以键入_。看来这可能是列表元素的类型,但事实并非如此,因为sorted的签名是 def sorted[B >: A](ordering: Ordering[B])。顺序可以在上A,但也可以在的任何祖先上进行A(您可以使用byHashCode : Ordering[Any] = Ordering.by(_.hashCode))。确实,列表是协变的事实迫使这种签名。一个可以做

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

但这真不愉快。


超级有帮助-我不确定我是否在问一个愚蠢的问题,但是我从你的回答中学到了很多!
schmmd 2011年

除非它不起作用。当我没有REPL时,我永远不应该回答。查看更新。
Didier Dupont

并在次要字段上排序,返回一个元组:list.sortBy(x => (-x.size, x.forTiesUseThisField))
布伦特·浮士德·浮士德

2
就我的观点而言,与其list.sorted(Ordering.by((_: TheType).size).reverse)考虑list.sorted(Ordering.by[TheType, Int](_.size).reverse)更清晰(但更长),不如说更合理。
樱桃2015年

5
我个人list.sortBy(_.size)(Ordering[Int].reverse)也喜欢。
dtech


27

也许再缩短一点:

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

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

19

容易起毛(至少在情况下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

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)

9

双方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更容易理解。



1

如果您传递的函数可能无法通过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

0

这是我的代码;)

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

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

1
这不是不正确的,但是有趣的部分(第二行)被其前面不需要的行淹没了。基本上,这里的要点是进行反向排序的一种方法是取消排序值。
卡尔·埃里克·门泽尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.