I'm building a widget to show medal counts for the Olympics. I have a collection of "country" objects, where each has a "name" attribute, and "gold", "silver", "bronze" for medal counts.
List should be sorted: 1. First by total medal count 2. If same medals, sub-sort by type (gold > silver > bronze, ie. two golds > 1 gold + 1 silver) 3. If same medals and type, sub-sort alphabetically
I'm doing this in ruby, but I suppose the language doesn't matter. I did figure out a solution, but if feels like there must be a much more elegant way to do it.
Here's what I did:
Create a virtual attribute with the weighted medal total. So if they had 2 gold and 1 silver, weighted total would be "3.020100". 1 gold and 1 silver and 1 bronze would be "3.010101"
Since we want to sort the medal count as highest first, list is sorted DESC. But then we want to sub-sort alphabetically (ie. ASC) after that. So I created a function which would alpha-invert a word (ie. "canada" => "xzmzwz")
Convert the weighted total to a string, concat the reversed name (ie. "3010101xzmzwz"), then sort descending. Voila.
By now, someone has figured out how to do the same thing in about 2 lines of code. Care to enlighten me?
countries.sort_by do |country|
medals = country.gold + country.silver + country.bronze
[-medals, -country.gold, -country.silver, country.name]
end
A simple method is to use sort_by with some arbitrary formatted string, like:
countries.sort_by do |c|
"%010d-%010d-%010d-%s" % [ c.gold, c.silver, c.bronze, c.name ]
end
This converts all the countries in to an ASCII sortable listing by padding the number of medals won to the presumably outrageous 10 places. If anyone wins more than ten billion medals your program may malfunction, but that seems like a reasonable constraint.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With