From: Gennady Bystritsky Date: 2006-08-15T07:02:52+09:00 Subject: Re: Consecutive sort on Array of Hashes > Hi, > > Here my - strange - problem. > > To explain it, let's take the example of football. I > construct an array > of hashes of the results with team_id, total of pts, number of wins, > number of draws and number of defeats such as: > > myArray = Array.new > myArray << {:team_id=>1, :pts=>5, :w=>0, :d=>5, :l=>5} > myArray << {:team_id=>2, :pts=>7, :w=>1, :d=>4, :l=>5} > myArray << {:team_id=>3, :pts=>4, :w=>0, :d=>4, :l=>6} > myArray << {:team_id=>4, :pts=>6, :w=>1, :d=>3, :l=>6} > myArray << {:team_id=>5, :pts=>5, :w=>0, :d=>5, :l=>5} > myArray << {:team_id=>6, :pts=>5, :w=>0, :d=>5, :l=>5} > myArray << {:team_id=>8, :pts=>10, :w=>2, :d=>4, :l=>4} > myArray << {:team_id=>9, :pts=>5, :w=>1, :d=>2, :l=>7} > myArray << {:team_id=>10, :pts=>8, :w=>1, :d=>5, :l=>4} > myArray << {:team_id=>11, :pts=>9, :w=>2, :d=>3, :l=>5} > myArray << {:team_id=>12, :pts=>6, :w=>1, :d=>3, :l=>6} > myArray << {:team_id=>13, :pts=>5, :w=>0, :d=>5, :l=>5} > > Now, from this array, I want to get the table. > So what I want to do is to sort the array, first by total of > pts, then > by number of wins (if 2 teams have the same total of points I > put first > the team with more wins) and then by number of draws. > > That's how - logically - I would do it anyway. But that does > not seem to > be the Ruby way. Doing it that way gives me a complete mess. > > No worries, doing it the other way round works (first sort by > draw, then > wins, then pts)! Here is what I run: > > puts "Team, Pts, W, D, L" > myArray = myArray.sort { |a,b| b[:d] <=> a[:d] > }.sort { |a,b| b[:w] <=> a[:w] > }.sort { |a,b| b[:pts] <=> a[:pts] > }.each do |row| > puts "#{row[:team_id]}, #{row[:pts]}, #{row[:w]}, #{row[:d]}, > #{row[:l]}" > end > > Did I say it works? Well almost! Here is my output: > > Team, Pts, W, D, L > 8, 10, 2, 4, 4 > 11, 9, 2, 3, 5 > 10, 8, 1, 5, 4 > 2, 7, 1, 4, 5 > 4, 6, 1, 3, 6 > 12, 6, 1, 3, 6 > 16, 5, 0, 5, 5 > 1, 5, 0, 5, 5 > 9, 5, 1, 2, 7 > 5, 5, 0, 5, 5 > 6, 5, 0, 5, 5 > 3, 4, 0, 4, 6 > > Good news, we kept the correct team_is with the correct result. > But can anyone explain me what on earth is the line 9, 5, 1, > 2, 7 doing > there in the middle? > > Thanks for your help! Each of your sort's just re-arranges the array by the new criteria, completely unrelated to previous sorts. Why not simply to create an appropriate criteria for a single sort: [ DISCLAIMER: Untested code bellow ] myArray = myArray.sort { |b, a| diff = 0 [ :pts, :w, :d ].each do |_criteria| diff = a[_criteria] - b[_criteria] break unless diff.zero? end diff } Or even cooler ;-) myArray = myArray.sort { |a, b| [ :pts, :w, :d ].inject(0) { |_m, _c| _m == 0 ? b[_c] - a[_c] : _m } } Gennady. > > -- > Posted via http://www.ruby-forum.com/. > >