Groovy Sort List
I am posting a simple example on how to sort a list in groovy because the examples google knows about aren't what I was looking for. With some deep digging I was able to find a clue that eventually solved my problem.
It's real easy to sort a list of numbers
assert [1,2,3,4] == [3,4,2,1].sort()
Or even strings
assert ['Chad','James','Travis'] == ['James','Travis','Chad'].sort()
But this was my example
class Person {def list = [new Person(id: '1', name: 'James'),new Person(id: '2', name: 'Travis'), new Person(id: '3', name: 'Chad')]
String id
String name
}
list.sort() returns James, Travis, Chad
The solution is ridiculously simple (not that I thought the previous sort would work; I have to be realistic; groovy can't do everything for me).
list.sort{it.name} will produce an order of Chad, James, Travis.
In the previous example note the use of the sort closure sort {} verses the sort() method.
Now I am not sure, off the top of my head and without a Groovy book handy, the simplest way to sort case insensitive.
assert ['a1','A1'] == ['A1,'a1'].sort{fancy closure}
39 comments:
You sir, are my friggin' hero. I've been messing with trying to create my own tag, etc for this, and you have the answer!
Thank you 10 times over!
Your post really helped me, James.
I found myself wanting case-insensitive sorting, too, so here's what worked for me (I tweaked your test data to make it more obvious):
assert ['a1', 'A2', 'a3'] == ['A2','a3', 'a1'].sort { a, b -> a.compareToIgnoreCase b }
Very helpful indeed - thanks for posting!
To no surprise, your post showed up in my google search for groovy list sorting ...
thanks again buddy
- Sturtz
Thank you very much :-)
GREAT! Thank you!
Wouldn't a better solution be to implement Comparable and override compareTo method?
thx bro :)
I looked for this for 2 days!!
Thanks
Good post indeed, but in most cases I think the Anonymous poster from March 1, 2009 9:44 PM had the better solution as it's more reusable.
"Wouldn't a better solution be to implement Comparable and override compareTo method?"
This is my solution:
class Person {
String id
String name
}
def list = [new Person(id: '1', name: 'James'),new Person(id: '2', name: 'Travis'), new Person(id: '3', name: 'Chad'),
new Person(id:'4', name:'angel')]
println list.name
// If you want to sort with Case sensitive, uncomment sort with spaceship operator <==> and comment the sort with compareToIgnoreCase
// list.sort { p1, p2 -> p1.name <=> p2.name }
list.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
println list.name
thanks for posting! It helped me just now and I bet it has helped far more than those who took the time to comment.
Yeah but, what if you wanted to reverse the sort order?
Much appreciated dude!!
To reverse sort order just add a dash before it. I just tried this (but for numeric values) and it worked.
list.sort{-it.name}
//Henrik Sjostrand
Nice, just what I was looking for. Thanks James.
To sort a list of map entries, use either:
list.sort{it.key}
or
list.sort{it.value}
Thanks for the great job.Can you give us an exmple of how do we apply this on GSPs?
Great Job there. Can you give also show us how we can apply this to our table listing on GSPs?
Fantastic, many thanks.
/Mattias
This post helped me greatly. Thanks. For reverse order I found that you need to add .reverse() to ones sort closure.
e.g.
myList.sort{ it.date}.reverse()
Is there any way to specify the order like in mysql we can specify "order by field(id, 2,3,1,4)". Can we specify such order on a property of domain class in grails criteria ?
To sort case sensitive:
assert ["b","A","C","d"].sort() == ["A","C","b","d"]
To sort case insensitive:
assert ["b","A","C","d"].sort{it.toLowerCase()} == ["A","b","C","d"]
thanks alot!
Thank you , it is still helping us.
Amazing... I find more and more answers to my questions on your blog. Big fan already. Thanks a bunch.
Thank you very much. This really helped a lot.
Anon in Feb asked about sorting with multiple db fields.
I just did this, here's my solution. Elegance upgrades welcome!
things.sort {thing1, thing2-> (thing1.field1<=>thing2.field1)?:(thing1.field2<=>thing2.field2)}
Love the terminology ... "Elvis and the spaceships"
Note, I actually wanted to reverse order the second field, so I negated the second sort:
things.sort {thing1, thing2-> (thing1.field1<=>thing2.field1)?:-(thing1.field2<=>thing2.field2)}
This is for two db fields ... multiple? does the structure hold up? for you to try if you want.
this blog even helped me...thanks a ton...
HOw to sort this array value??
data = [[1,23],[1,13],[2,543],[2,573]]
I want to sort on the basis of second value of array like
[[1,13],[1,23],[2,543],[2,573]]
Thanks
to Sonu
[[1,23],[1,13],[2,543],[2,573]].sort {a, b -> a[1].compareTo(b[1])}
Incredibly helpful. Thank you so much.
If you want case insensitive searching but also protection from nulls, try:
.sort {it.name?.toLowerCase()}
This continues to be very valuable information. Thanks for posting it.
Five years later, James's post is still the best thing on the web for Groovy newcomers, like me.
After I used this to get my sorting done, I tried it again, but made the very mistake that the original post had warned about--using parentheses instead of curly braces (sorry, James, I need to read more slowly).
Watch out for this mistake -- it produces mysterious error messages, such as "Cannot get property 'name' on null object" or "No such property: it for class".
This experience prodded me into figuring out what the curly-brace syntax was actually doing
(see http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html#sort(java.util.Comparator) )
which in turn suggests what I believe is the simplest solution to case-insensitive sorting (at least it worked for me):
list.sort {it.name.toLowerCase()}
Oops! I now see that Anonymous beat me to that case-insensitive solution by about five months -- and with more robust code too.
Oops again. The documentation link I posted should have been to the overloading of sort() that uses a closure:
http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html#sort(groovy.lang.Closure)
WOW, that was simple, thanks!
you just saved me a bunch of extra work. thank you
Post a Comment