Sort, sort_by and group_by
Posted by Andre Foeken Sun, 29 Jul 2007 14:57:24 GMT
I wanted to put the spotlight on some small but very useful ruby on rails functions: sort, sort_by and group_by.
Let's start with sort and sort_by. Its basic function should not come as a surprise: it sorts a list.
[1,3,2,4].sort => [1,2,3,4]
These functions really shine when you use objects inside the list.
a = { :key => 0, :value => 'a', :extra => 0 }
b = { :key => 1, :value => 'b', :extra => 0 }
c = { :key => 2, :value => 'c', :extra => 1 }
d = { :key => 3, :value => 'd', :extra => 1 }
[a,c,d,b].sort_by{ |i| i[:key] } => [a,b,c,d]
The previous example already contains the correct objects to demonstrate the use of group_by so we just give that example now.
[a,b,c,d].group_by{ |i| i[:extra] } => [ 0=>[a,b], 1=>[c,d] ]
As you can see this gives us the power of the SQL group_by statements right inside ruby. Sure, this cannot beat the speed of the SQL equivalent. But sometimes when speed is not really an issue or when you just can't query the right results, group_by can be a real life-saver.
As a bonus, when you want to group_by or sort_by functions on objects, you can use this pretty shorthand:
[a,b,c,d].group_by(&:length) => [ 3 => [a,b,c,d] ]
If you are wondering why the above works, it is just basic ruby. Any function that is defined to receive a &block can be called by either giving it a block of code in parenthesis or by passing it a proc object. The &:length is just shorthand for &proc{ |i| i.length }. Too bad you can't pass it arguments using the shorthand, then you'd be able to write:
[a,b,c,d].group_by(&:fetch, :key)
Hope you find this useful, if anyone knows if the above code is indeed possible in another form, please comment!
Update: I recently found out you can also use arrays in combination with these functions. So you can sort by multiple values. If you pass array [a,b] to a sort function it will sort by a and then sort by b. Very handy!

Thanks for the tips, but how to combine both of them?
Depends on what you want. You can easily sort groups of the group_by functions using the map method. You can't cleanly sort the group_keys that result from the group_by method, since they are returned as a hash. Your best off just sorting the keys and get them one by one...
Love playing backgammon? Visit us at Backgammon site for backgammon FAQ, backgammon rules, online backgammon guide, articles, and much more.
Thanks for the tips, they have proved most useful! One question, I want to sort a group by based on a :key, but be able to display the :value. I have in a method in my model that returns a hash with :key and :value. In my controller I am grouping by the :key In my view, I am sorting by the :key, but I want to be able to display the :value. The controller is only passing the :key, any thoughts on passing both the :key and the :value? I haven't looked at the map method, how would that work?
This is awesome! Thanks for the quickie :) -- Maku http://www.ApnaBill.com
nice post. can also post a tip about using this "sort_by=". I tried that one of my site but not get it yet.