How to sort a list by existing properties
groovy, java, sorting
Solution
I'm not sure I understand your question correctly. Maybe something like this is what you are looking for:
def things = [
[name: 'aaa', title: '222'],
[name: 'aaa', title: '333'],
[title: '222'],
[title: '111'],
[name: 'bbb', title: '111'],
[title: '333'],
[name: 'aaa', title: '111'],
]
things.sort { a, b ->
// Compare by name and then by title.
a.name <=> b.name ?: a.title <=> b.title
}
assert things == [
[title: '111'],
[title: '222'],
[title: '333'],
[name: 'aaa', title: '111'],
[name: 'aaa', title: '222'],
[name: 'aaa', title: '333'],
[name: 'bbb', title: '111'],
]
What's happening inside that seemingly innocent comparison function is actually quite a lot of Groovy syntax magic. But it's not too difficult to follow.
First, the `sort` method is being invoked with a binary function that acts as a comparator (i.e. takes two arguments, a and b and returns -1 if a < b, 1 if a > b and 0 if a == b).
This anonymous function: `{ a, b -> a.name <=> b.name ?: a.title <=> b.title }` uses the "spaceship operator" (`<=>`... that's a spaceship man!) to first compare a and b by names.
If the names are equal (or both null), then the result of `a.name <=> b.name` is 0, which evaluates falsely in the "Elvis operator" (`?:`... imagine it as a smiley), so then the result of `a.title <=> b.title` is returned.
Otherwise, if the result of the name comparison is not 0, then that evaluates truthfully in the Elvis operator and that value is returned.
This is all taking into consideration that you can compare null values with strings and that `'any string' > null` always holds (which is the same as saying that `'any string' <=> null == 1`).
So the final result is that elements with no name are first and sorted by title, and then the elements with name and title are ordered first by name and then by title.
I hope that was what you were looking for. If you were expecting a different ordering of the sorted elements feel free to clarify it in the comments :)
Update
There is also a not very documented `OrderBy` object that can be used in this case:
things.sort new OrderBy([{it.name}, {it.title}])
Problem
I am using this line here to sort a list based on the object's name. ``` g.V.sort{it.name} ``` How do I sort it based on "name" if it exists, if not, I wanna sort it by "title". If both exist I want to first sort by "name" and then by "title". I'm not a Groovy coder so thanks for the help in advance.