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.
sort() method to sort a list of objects using some examples. By default, the sort() method sorts a given list into ascending order (or natural order). We can use Collections. reverseOrder() method, which returns a Comparator, for reverse sorting.
Java 8 introduced a sort method in the List interface which can use a comparator. The Comparator. comparing() method accepts a method reference which serves as the basis of the comparison. So we pass User::getCreatedOn to sort by the createdOn field.
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 :)
There is also a not very documented OrderBy
object that can be used in this case:
things.sort new OrderBy([{it.name}, {it.title}])
You can sorts the Collection using a Comparator
.
g.V.sort { a, b ->
a.name <=> b.name ?: a.title <=> b.title
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With