Groovy list.sort by first, second then third elements
Solution 1
You should be able to iterate through the desired sorting in reverse order:
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]]
Each should override the previous just enough to keep the combined sorting intact.
You can also chain them in order with the Elvis operator, ?:
, which will defer to the next comparison when the previous are equal (and <=>
returns 0
):
list.sort { a,b -> a[0] <=> b[0] ?: a[1] <=> b[1] ?: a[2] <=> b[2] }
Solution 2
If you want to sort arrays of arbitrary (though homogenous) length, you can use this and it will do it in a single pass:
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]]
Solution 3
Here is another method using Groovy's Spaceship and Elvis operators:
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]]
Source: Groovier way of sorting over multiple fields in a list of maps in groovy
Solution 4
you can use kobo-commons' CollectionUtils library.
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]]
Solution 5
Done the Groovy way, regardless of the size of sub-lists:
ll2.sort { l1, l2 ->
e1e2 = [l1, l2].transpose().find { e1, e2 ->
e1 != e2
}
e1e2 ? e1e2[0] <=> e1e2[1] : 0
}
Admin
Updated on September 03, 2021Comments
-
Admin over 2 years
I have a groovy list of lists i.e.
list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
I would like sort it by order of the first element, then second, then third.
Expected
assert list == [[1, 0, 3], [1, 5, 2], [2, 0, 1]]
I started with
list = list.sort{ a,b -> a[0] <=> b[0] }
but that only sorts the first element. How do you finish?Thanks