Scalaで逆ソートする最良の方法は何ですか?


137

Scalaで逆ソートを行う最良の方法は何ですか?以下は少し遅いと思います。

list.sortBy(_.size).reverse

sortByを使用する便利な方法はありますか?を使用する必要はありません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( "incorrect way")println(clock.toString)[正しい方法、lap = 76、dur。= 76] | [間違った方法、ラップ= 326、デュア。= 250]
コア2017年

回答:


241

数値でソートする場合、符号を変更する明らかな方法があるかもしれません

list.sortBy(- _.size)

より一般的には、ソートは暗黙的なOrderingでソートされたメソッドによって行われる場合があり、これは明示的に行うことができ、Orderingは逆になります(以下のリストの逆ではありません)

list.sorted(theOrdering.reverse)

逆にしたい順序が暗黙的な順序である場合は、暗黙的に[Ordering [A]](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])。順序はである可能性がありますがAA(あなたが使用するかもしれない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)それをより明確に(ただしより長く)考える。
チェリー

5
個人的にlist.sortBy(_.size)(Ordering[Int].reverse)も好きです。
dtech 2016年


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

sortByord順序付けを提供する暗黙のパラメータがあります

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
これは間違いではありませんが、興味のある部分(2行目)は、その前の不要な行によって溺れてしまいます。基本的に、ここでのポイントは、逆ソートを行う1つの方法は、ソート値を否定することです。
Carl-Eric Menzel、2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.