Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort a list with multiple conditions Ruby on Rails

I want to be able to rank 12 teams in a list according to 4 different criteria.

I will have a db table called Teams and each team will have various columns like matches_won, matches_lost, etc...

I want to display them in order based on matches_won. This is easy. However, if two teams are tied in matches_won then I must check whether they have played each other and who won. If they have the same matches_won AND have not played each other, their records are compared on two other criteria and ranked by that. I think if I can figure out how to do one additional condition to the sort that I will be able to figure out how to do the others. So for brevity's sake, I won't detail them here.

I don't know how to do this multi-level sorting in Rails.

I have thought maybe adding a 'rank' column in the db table and before_save function that ranks them going into the db and then simply listing them in the view based on that rank. But that leaves me with the same problem (not knowing how to do conditional sorting) it just does it before the save rather than when I read it out of the db.

Any help would be appreciated!

like image 757
Jonathon Doesen Avatar asked Jan 10 '12 01:01

Jonathon Doesen


1 Answers

Use sort_by and supply an array of values. It will compare them in order from left to right. Default sort is ascending, so if you want the opposite (e.g. matches_won should sort descendingly so that most matches one comes first, as opposed to matches_lost, which should sort lowest to highest), you need to negate the value.

Here's an example

require 'pp'
Team = Struct.new :won, :lost, :demerits, :style

teams = Array.new(20) { Team.new rand(5), rand(5), rand(5), rand(5) }
puts "Before sort:"
pp teams

puts "", "After sort:"
pp teams
teams.sort_by! { |team| [-team.won, team.lost, team.demerits, -team.style] }
# >> Before sort:
# >> [#<struct Team won=1, lost=2, demerits=4, style=3>,
# >>  #<struct Team won=0, lost=4, demerits=2, style=2>,
# >>  #<struct Team won=4, lost=1, demerits=2, style=3>,
# >>  #<struct Team won=1, lost=4, demerits=1, style=4>,
# >>  #<struct Team won=3, lost=1, demerits=1, style=4>,
# >>  #<struct Team won=3, lost=4, demerits=1, style=2>,
# >>  #<struct Team won=4, lost=0, demerits=4, style=0>,
# >>  #<struct Team won=3, lost=4, demerits=1, style=2>,
# >>  #<struct Team won=1, lost=4, demerits=1, style=2>,
# >>  #<struct Team won=3, lost=0, demerits=1, style=1>,
# >>  #<struct Team won=3, lost=4, demerits=3, style=4>,
# >>  #<struct Team won=1, lost=4, demerits=0, style=0>,
# >>  #<struct Team won=3, lost=4, demerits=2, style=0>,
# >>  #<struct Team won=3, lost=0, demerits=3, style=0>,
# >>  #<struct Team won=1, lost=2, demerits=0, style=1>,
# >>  #<struct Team won=3, lost=0, demerits=1, style=0>,
# >>  #<struct Team won=0, lost=4, demerits=1, style=4>,
# >>  #<struct Team won=1, lost=4, demerits=3, style=0>,
# >>  #<struct Team won=3, lost=3, demerits=2, style=3>,
# >>  #<struct Team won=0, lost=4, demerits=4, style=4>]
# >> 
# >> After sort:
# >> [#<struct Team won=4, lost=0, demerits=4, style=0>,
# >>  #<struct Team won=4, lost=1, demerits=2, style=3>,
# >>  #<struct Team won=3, lost=0, demerits=1, style=1>,
# >>  #<struct Team won=3, lost=0, demerits=1, style=0>,
# >>  #<struct Team won=3, lost=0, demerits=3, style=0>,
# >>  #<struct Team won=3, lost=1, demerits=1, style=4>,
# >>  #<struct Team won=3, lost=3, demerits=2, style=3>,
# >>  #<struct Team won=3, lost=4, demerits=1, style=2>,
# >>  #<struct Team won=3, lost=4, demerits=1, style=2>,
# >>  #<struct Team won=3, lost=4, demerits=2, style=0>,
# >>  #<struct Team won=3, lost=4, demerits=3, style=4>,
# >>  #<struct Team won=1, lost=2, demerits=0, style=1>,
# >>  #<struct Team won=1, lost=2, demerits=4, style=3>,
# >>  #<struct Team won=1, lost=4, demerits=0, style=0>,
# >>  #<struct Team won=1, lost=4, demerits=1, style=4>,
# >>  #<struct Team won=1, lost=4, demerits=1, style=2>,
# >>  #<struct Team won=1, lost=4, demerits=3, style=0>,
# >>  #<struct Team won=0, lost=4, demerits=1, style=4>,
# >>  #<struct Team won=0, lost=4, demerits=2, style=2>,
# >>  #<struct Team won=0, lost=4, demerits=4, style=4>]
like image 75
Joshua Cheek Avatar answered Oct 19 '22 05:10

Joshua Cheek