Problem sorting

I am trying to sort an array using a block but somehow I am not seeing
what I am want. First I want to sort the total, then break the tie on
gold goldcount, silvercount and finally on bronzcount

Here is my code. what am I missing? please help

compare and order by totals

    result = b[:total] <=> a[:total]
    # if tied, break the number of gold medals
    result != 0 ? result : b[:goldcount] <=> a[:goldcount]
    result != 0 ? result : b[:silvercount] <=> a[:silvercount]
    result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
    result != 0 ? result : b[:country] <=> a[:country]

end

At 2010-03-25 10:58AM, “Augusto G.” wrote:

     result != 0 ? result : b[:silvercount] <=> a[:silvercount]
     result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
     result != 0 ? result : b[:country] <=> a[:country]

You’re not assigning the tiebreaker back to the ‘result’ variable

# compare

    result = b[:total] <=> a[:total] ||
             b[:goldcount] <=> a[:goldcount] ||
             b[:silvercount] <=> a[:silvercount] ||
             b[:bronzcount] <=> a[:bronzcount] ||
             b[:country] <=> a[:country]

It might be clearer to use sort_by instead of sort

sorted = array.sort_by do |h|
  [ 

h[:total],h[:goldcount],h[:silvercount],h[:bronzecount],h[:country] ]
end

On Thu, Mar 25, 2010 at 3:58 PM, Augusto G. [email protected] wrote:

   result != 0 ? result : b[:silvercount] <=> a[:silvercount]
   result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
   result != 0 ? result : b[:country] <=> a[:country]

end

I assume you have an array of hashes:

irb(main):001:0> country_medals = []
=> []

irb(main):002:0> country_medals << {:country => “Spain”, :total =>
100, :goldcount => 100, :silvercount => 0, :bronzecount => 0}
=> [{:country=>“Spain”, :total=>100, :goldcount=>100, :silvercount=>0,
:bronzecount=>0}]

irb(main):003:0> country_medals << {:country => “US”, :total => 50,
:goldcount => 50, :silvercount => 0, :bronzecount => 0}
=> [{:country=>“Spain”, :total=>100, :goldcount=>100, :silvercount=>0,
:bronzecount=>0}, {:country=>“US”, :total=>50, :goldcount=>50,
:silvercount=>0, :bronzecount=>0}]

irb(main):004:0> country_medals << {:country => “UK”, :total => 50,
:goldcount => 45, :silvercount => 5, :bronzecount => 0}
=> [{:country=>“Spain”, :total=>100, :goldcount=>100, :silvercount=>0,
:bronzecount=>0}, {:country=>“US”, :total=>50, :goldcount=>50,
:silvercount=>0, :bronzecount=>0}, {:country=>“UK”, :total=>50,
:goldcount=>45, :silvercount=>5, :bronzecount=>0}]

irb(main):010:0> country_medals.sort_by {|x| [-x[:total],
-x[:goldcount], -x[:silvercount], -x[:bronzecount], x[:country]]}
=> [{:country=>“Spain”, :total=>100, :goldcount=>100, :silvercount=>0,
:bronzecount=>0}, {:country=>“US”, :total=>50, :goldcount=>50,
:silvercount=>0, :bronzecount=>0}, {:country=>“UK”, :total=>50,
:goldcount=>45, :silvercount=>5, :bronzecount=>0}]

Jesus.

Since no one has duplicated what you seemed to be trying:

On Mar 25, 2010, at 11:31 AM, Jesús Gabriel y Galán wrote:

   result = b[:total] <=> a[:total]
   # if tied, break the number of gold medals
   result != 0 ? result : b[:goldcount] <=> a[:goldcount]
   result != 0 ? result : b[:silvercount] <=> a[:silvercount]
   result != 0 ? result : b[:bronzcount] <=> a[:bronzcount]
   result != 0 ? result : b[:country] <=> a[:country]

end

.sort {|a,b|
(b[:total] <=> a[:total]).nonzero? ||
(b[:goldcount] <=> a[:goldcount]).nonzero? ||
(b[:silvercount] <=> a[:silvercount]).nonzero? ||
(b[:bronzcount] <=> a[:bronzcount]).nonzero? ||
b[:country] <=> a[:country]
}

Look at what Numeric#nonzero? is meant for :wink:

Also, your original breaks the final tie by reverse sort of the
country so I do here as well. Augusto has an ascending sort on all and
Jesús just has an ascending sort on the country.

-Rob

irb(main):003:0> country_medals << {:country => “US”, :total => 50,
:goldcount=>45, :silvercount=>5, :bronzecount=>0}]

Rob B. http://agileconsultingllc.com
[email protected]