web-dev-qa-db-ja.com

Groovy list.sortを最初、2番目、3番目の要素で並べ替える

リストのグルーヴィーなリストがあります。

list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

最初の要素、2番目、3番目の順に並べ替えたいと思います。

期待される

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]

list = list.sort{ a,b -> a[0] <=> b[0] }から始めましたが、それは最初の要素のみをソートします。どのように終了しますか?

ありがとう

26
user177983

目的の並べ替えを逆の順序で繰り返すことができるはずです。

list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

list = list.sort{ a,b -> a[2] <=> b[2] }
list = list.sort{ a,b -> a[1] <=> b[1] }
list = list.sort{ a,b -> a[0] <=> b[0] }

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]

それぞれは、結合されたソートをそのまま維持するのに十分なだけ前のものをオーバーライドする必要があります。


エルビス演算子、?: を使用して順番にチェーンすることもできます。これにより、前の比較が等しい場合に次の比較が延期されます(<=>0を返します)。 )::

list.sort { a,b -> a[0] <=> b[0] ?: a[1] <=> b[1] ?: a[2] <=> b[2] }
28

任意の(均一ではあるが)長さの配列をソートしたい場合は、これを使用でき、シングルパスでそれを実行します。

def list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

list.sort { a, b -> 
    for (int i : (0..<a.size())) {
        def comparison = (a[i] <=> b[i])
        if (comparison) return comparison
    } 
    return 0
}

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
8
Ted Naleid

Groovyの 宇宙船 および エルビス 演算子を使用する別の方法を次に示します。

​def list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]

list.sort { a, b ->
   a[0] <=> b[0] ?: a[1] <=> b[1] ?: a[2] <=> b[2]
}

assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]​

ソース: groovyのマップのリスト内の複数のフィールドをソートするGroovierの方法

6
cweston

kobo-commonsのCollectionUtilsライブラリを使用できます。

https://github.com/kobo/kobo-commons/wiki/sort-by-multiple-keys

import org.jggug.kobo.commons.lang.CollectionUtils

CollectionUtils.extendMetaClass()


list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
list = list.sort{ [ it[0], it[1], it[2] ]} // sort by multiple keys
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]

list2 = [ [name:"a", age:13], [name:"a",age:15], [name:"b", age:13] ]
list2 = list2.sort{[it.name, it.age] } // sort by name and age
assert list2 == [[name:"a", age:13], [name:"a", age:15], [name:"b", age:13]]
4
user303546

サブリストのサイズに関係なく、Groovyの方法で実行します。

ll2.sort { l1, l2 ->
  e1e2 = [l1, l2].transpose().find { e1, e2 ->
      e1 != e2
  }
  e1e2 ? e1e2[0] <=> e1e2[1] : 0
}
2
Bahman Movaqar

あなたは一行でそれを行うことができます:

list.sort { String.format('%010d%010d%010d', it[0], it[1], it[2]) }
0

これが私が思いついたものであり、私が思う最もグルーヴィーな方法ではありません。

list = list.sort{ a,b -> 
    if(a[0].compareTo(b[0]) == 0) {
        if(a[1].compareTo(b[1]) == 0) {
            return a[2].compareTo(b[2]);
        } else {
            return a[1].compareTo(b[1]);
        }
    } else {
        return a[0].compareTo(b[0]);
    }
}
0
user177983