Сортировать коллекцию объектов по номеру (сначала по возрастанию), затем по буквам (по алфавиту) - PullRequest
5 голосов
/ 09 февраля 2010

Я создаю виджет для отображения количества медалей на Олимпиаде. У меня есть коллекция объектов "страна", где у каждого есть атрибут "имя" и "золото", "серебро", "бронза" для подсчета медалей.

Список должен быть отсортирован: 1. Сначала по общему количеству медалей 2. Если одинаковые медали, подгруппируйте по типу (золото> серебро> бронза, т.е. два золота> 1 золото + 1 серебро) 3. Если одинаковые медали и тип, под сортировка в алфавитном порядке

Я делаю это в рубине, но я полагаю, что язык не имеет значения. Я нашел решение, но если кажется, что должен быть более элегантный способ сделать это.

Вот что я сделал:

  1. Создание виртуального атрибута с итоговой взвешенной медалью. Таким образом, если бы у них было 2 золота и 1 серебро, взвешенный итог был бы «3.020100». 1 золото, 1 серебро и 1 бронза будут «3.010101»

  2. Так как мы хотим отсортировать количество медалей по наибольшему первому, список сортируется DESC. Но затем мы хотим отсортировать по алфавиту (т.е. ASC) после этого. Поэтому я создал функцию, которая будет инвертировать слово в альфа-формате (например, "canada" => "xzmzwz")

  3. Преобразовать взвешенную сумму в строку, объединить обратное имя (т. Е. «3010101xzmzwz»), а затем отсортировать по убыванию. Вуаля.

К настоящему времени кто-то понял, как сделать то же самое с помощью примерно двух строк кода. Хотите просветить меня?

Ответы [ 3 ]

10 голосов
/ 10 февраля 2010
countries.sort_by do |country|
  medals = country.gold + country.silver + country.bronze
  [-medals, -country.gold, -country.silver, country.name]
end
1 голос
/ 10 февраля 2010

Простой метод - использовать sort_by с какой-либо произвольно отформатированной строкой, например:

countries.sort_by do |c|
  "%010d-%010d-%010d-%s" % [ c.gold, c.silver, c.bronze, c.name ]
end

Это превращает все страны в сортируемый список ASCII, дополняя число завоеванных медалей до предположительно возмутительных 10 мест. Если кто-то выиграет более десяти миллиардов медалей, ваша программа может работать неправильно, но это кажется разумным ограничением.

0 голосов
/ 10 февраля 2010

В Java вы реализуете сопоставимый для вашего объекта, и тогда его можно легко отсортировать в ArrayList или Array. Есть ли в Ruby механизм, позволяющий сравнивать два ваших объекта "Страна"?

...