ScalaのsortedやsortByで降順にする

2024/06/21に公開2

ScalaでsortedやsortByを使ったとき昇順に並びますが、降順にするにはどうすれば良いのかと思いググったらstackoverflowに神アンサーがあったのでそれを踏まえた降順にするコードのメモです。

https://stackoverflow.com/questions/7802851/whats-the-best-way-to-inverse-sort-in-scala

sortedの結果に.reverseをつける

これはstackoverflowに載っているわけではないのですが、ぱっと浮かぶ方法でしょう。

scala> Seq(3, 1, 2).sorted
val res1: Seq[Int] = List(1, 2, 3)

scala> Seq(3, 1, 2).sorted.reverse
val res2: Seq[Int] = List(3, 2, 1)

sortByの数字にマイナスをつける

これは確かに〜〜〜〜〜ってなりましたw

scala> case class Hoge(n: Int)
// defined case class Hoge

scala> Seq(Hoge(1), Hoge(0), Hoge(10)).sortBy(- _.n)
val res5: Seq[Hoge] = List(Hoge(10), Hoge(1), Hoge(0))

sortedのimplicit parameterのOrderingにreverseをつける

これが載っていた方法なのですが、なるほどとなりました。
sortedやsortByの引数には順番を決めるOrderingを渡せるようになっていますが、そこに逆順であることを明示して渡せば良いということでした。
考えてみればそうだなと思ったんですが、気づけていなかったので目からウロコでした。

scala> Seq(3, 1, 2).sorted(Ordering[Int].reverse)
val res3: Seq[Int] = List(3, 2, 1)

scala> case class Hoge(n: Int)
// defined case class Hoge

scala> Seq(Hoge(1), Hoge(0), Hoge(10)).sortBy(_.n)(Ordering[Int].reverse)
val res4: Seq[Hoge] = List(Hoge(10), Hoge(1), Hoge(0))

Ordering.byを使う

sortByに近いような形でやるOrdering.byを使っても書けるようです。

scala> Seq(Hoge(1), Hoge(0), Hoge(10)).sorted(Ordering.by((_: Hoge).n).reverse)
val res7: Seq[Hoge] = List(Hoge(10), Hoge(1), Hoge(0))

まとめ

  • マイナスをつけて目がすべるよりは型でやれると良さそうw
  • Orderingを引数に渡すでもいいし、Ordering.byを作って渡す形も良さそう
GitHubで編集を提案

Discussion

kenji yoshidakenji yoshida

マイナスつける方法は Int.MinValue が含まれてるとバグります

ara_ta3ara_ta3

なるほど、なおのことやる理由がなくなりました

scala> case class Hoge(a: Int)
// defined case class Hoge

scala> Seq(Hoge(10), Hoge(1), Hoge(-10), Hoge(Int.MinValue)).sortBy(_.a)
val res2: Seq[Hoge] = List(Hoge(-2147483648), Hoge(-10), Hoge(1), Hoge(10))

scala> Seq(Hoge(10), Hoge(1), Hoge(-10), Hoge(Int.MinValue)).sortBy(- _.a)
val res3: Seq[Hoge] = List(Hoge(-2147483648), Hoge(10), Hoge(1), Hoge(-10))