LoginSignup
3

More than 5 years have passed since last update.

[Groovy]リストに格納されたオブジェクトを複数のキーを元にソートする

Last updated at Posted at 2016-04-07

Groovyでは <=>という演算子が有ります。
この演算子は宇宙船演算子というらしいです(PHP7情報)
やっと名前を知ることが出来たのでじゃあ一体ドコで使うの?というサンプルを投稿します。
まぁタイトルに有るとおりソートで威力を発揮します!

シンプルなサンプルとして、数値が格納されたリストを昇順にソートしてみます。

assert [1,2,3,4,5] == [3,1,5,4,2].sort {left, right -> left <=> right}

GroovyのListのsortメソッドは、リストの先頭から自動的に1つめと2つ目の値を、渡すクロージャに渡してくれるので、その値に対して例の宇宙船演算子<=>を指定するだけです。
じゃあ降順は?という話になりますね。はい簡単です。単純に比較順序を逆にするだけです。

assert [5,4,3,2,1] == [3,1,5,4,2].sort {left, right -> right <=> left}

こんな感じで、Groovyではお手軽にリストの中身をソートできます。宇宙船演算子とクロージャのおかげですね!

ただ、コレだけだとググれば山ほど出てくるので、今回は複数のキーをソート対象にしてみます。
条件は、

  1. リストにクラスAのインスタンスを格納する。
  2. そのリスト内のAインスタンスをそれぞれ、プロパティaの値で降順でソートする。
  3. ただし、プロパティaの値が同じ場合は、プロパティbの値で比較して、降順でソートする。

です。
ココで新しいキーワード?:が出てきます。コレはエルビス演算子というものです。プレスリー!!
コレは、左辺がtrueなら左辺を、左辺がfalseなら右辺を返すというイカした演算子です。

groovy:000> assert 100 == 0?:100
===> null
groovy:000> assert 100 == 100?:0
===> null

このエルビス演算子を利用すると、NULLチェックをしてNULLなら別の値を入れて。。。というような作業を更にスマートに表現できる可能性が高まります。

Date d = null
println d ?: "oh... Dateがヌルダヨー"

エルビス演算子の詳細はまた別途投稿したいと思います。
では、これらを組み合わせてソートを実装してみます。

class A{
    def a
    def b
}

assert ["a=2, b=1", "a=1, b=2", "a=1, b=1"] == [
    new A(a:1,b:1), 
    new A(a:1,b:2), 
    new A(a:2,b:1)
].sort{ l,r -> 
    r.a<=>l.a ?: r.b<=>l.b
}.collect {"a=${it.a}, b=${it.b}"}

ちょっと見辛いですね。
実行結果としては当然、

a=2, b=1
a=1, b=2
a=1, b=1

という並びになっています。

以上です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3