Groovy Goodness: Sorting Data With GINQ
GINQ (Groovy-INtegerate Query) is part of Groovy since version 4. With GINQ we can use SQL-like queries to work with in-memory data collections. If we want to sort the data we can use orderby
followed by the property of the data we want to sort just like in SQL we can use order by
. By default the sort ordering is ascending and null
values are put last. We can change the sort ordering by specifying in desc
with the orderby
clause. Or to make the ascending order explicitly we use the statement in asc
. Each of asc
and desc
also can take an argument to specify how we want null
values to be sorted. The default way is to keep null
values last in the ordering. If we want to make this explicit we use nullslast
as argument to asc
or desc
. To have null
values in the sorted result first we use the argument nullsfirst
.
The following example shows all use cases for using orderby
when using GINQ:
import groovy.json.JsonSlurper
// Parse sample JSON with a list of users.
def json = new JsonSlurper().parseText('''[
{ "username": "mrhaki", "email": "mrhaki@localhost" },
{ "username": "mrhaki", "email": "user@localhost" },
{ "username": "hubert", "email": "user@localhost" },
{ "username": "hubert", "email": "hubert@localhost" },
{ "username": "hubert", "email": null }
]''')
// Helper method to return a String
// representation of the user row.
def formatUser(row) {
row.username + "," + row.email
}
// Default ordering is ascending.
// We specify the field name we want to order on.
assert GQ {
from user in json
orderby user.username
select formatUser(user)
}.toList() == [
'hubert,user@localhost',
'hubert,hubert@localhost',
'hubert,null',
'mrhaki,mrhaki@localhost',
'mrhaki,user@localhost'
]
// We can explicitly set ordering to ascending.
assert GQ {
from user in json
orderby user.email in asc
select formatUser(user)
}.toList() == [
'hubert,hubert@localhost',
'mrhaki,mrhaki@localhost',
'mrhaki,user@localhost',
'hubert,user@localhost',
'hubert,null'
]
// By default null values are last.
// We can also make this explicit as
// option to in asc() or in desc().
assert GQ {
from user in json
orderby user.email in asc(nullslast)
select formatUser(user)
}.toList() == [
'hubert,hubert@localhost',
'mrhaki,mrhaki@localhost',
'mrhaki,user@localhost',
'hubert,user@localhost',
'hubert,null'
]
// We can combine multiple properties to sort on.
assert GQ {
from user in json
orderby user.username, user.email
select formatUser(user)
}.toList() == [
'hubert,hubert@localhost',
'hubert,user@localhost',
'hubert,null',
'mrhaki,mrhaki@localhost',
'mrhaki,user@localhost'
]
// To order descending we must specify it
// as in desc.
assert GQ {
from user in json
orderby user.username in desc
select formatUser(user)
}.toList() == [
'mrhaki,mrhaki@localhost',
'mrhaki,user@localhost',
'hubert,user@localhost',
'hubert,hubert@localhost',
'hubert,null'
]
// We can mix the ordering and set it
// differently for each property.
assert GQ {
from user in json
orderby user.username in asc, user.email in desc
select formatUser(user)
}.toList() == [
'hubert,user@localhost',
'hubert,hubert@localhost',
'hubert,null',
'mrhaki,user@localhost',
'mrhaki,mrhaki@localhost'
]
// By default all null values are last,
// but we can use nullsfirst to have null
// values as first value in the ordering.
assert GQ {
from user in json
orderby user.username in asc, user.email in desc(nullsfirst)
select formatUser(user)
}.toList() == [
'hubert,null',
'hubert,user@localhost',
'hubert,hubert@localhost',
'mrhaki,user@localhost',
'mrhaki,mrhaki@localhost'
]
Written with Groovy 4.0.11.