tags:

views:

314

answers:

3
+4  Q: 

ruby sort_by twice

Ruby has a sort_by method on Enumerables. Fantastic! So you can do something like

entries.sort_by { |l| l.project.name }

That would sort a bunch of entries by their project names. How could you work it so that within projects that had the same name, entries were sorted by their time?

A: 

You can use the regular sort method to do it.

entries.sort do |a, b|
  comp = a.project.name <=> b.project.name
  comp.zero? ? (a.project.time <=> b.project.time) : comp
end
ahlatimer
the nonzero? method can be helpful here: sort {|a,b| (a.project.name <=> b.project.name).nonzero? or (a.project.time <=> b.project.time)}
glenn jackman
+10  A: 

I would suggest putting the column you want to sort by into an array.

entries.sort_by { |l| [l.project.name, l.project.time] }

This will respect the natural sort order for each type.

brianegge
If you want the secondary sort to be most-recent-first, do this: `now = Time.now; entries.sort_by { |e| e.project.name, now - e.project.time }`
James A. Rosen
entries.sort_by { |e| e.project.name, -e.project.time }makes more sense.
Antti Tarvainen
Not bad Antti, not bad at all!
James A. Rosen
+1  A: 

Return an array:

entries.sort_by { |l| [ l.project.name, l.project.time] }

this works because the <=> operator on arrays does a field-by-field 'lexical' comparison which is what you're looking for.

Dave Ray