Сортировка коллекции объектов по номеру (сначала по наибольшему значению), затем по букве (в алфавитном порядке).
-
19-09-2019 - |
Вопрос
Я создаю виджет для отображения количества медалей на Олимпийских играх.У меня есть коллекция объектов «страна», каждый из которых имеет атрибут «имя» и «золото», «серебро», «бронза» для подсчета медалей.
Список должен быть отсортирован:1.Сначала по общему количеству медали 2.Если медали одинаковые, отсортируйте их по типу (золото > серебро > бронза, т. е.Два золота> 1 золото + 1 серебро) 3.Если медали и тип одинаковы, отсортируйте их по алфавиту.
Я делаю это на Ruby, но полагаю, язык не имеет значения.Я нашел решение, но мне кажется, что должен быть гораздо более элегантный способ сделать это.
Вот что я сделал:
Создайте виртуальный атрибут с взвешенной суммой медалей.Таким образом, если бы у них было 2 золота и 1 серебро, взвешенная сумма была бы «3,020100».1 золото, 1 серебро и 1 бронза будут равны «3.010101».
Поскольку мы хотим отсортировать количество медалей сначала по наибольшему, список сортируется по DESC.Но тогда мы хотим выполнить сортировку по алфавиту (т.ASC) после этого.Поэтому я создал функцию, которая инвертирует слово в альфа-канале (т."Канада" => "xzmzwz")
Преобразуйте взвешенную сумму в строку, соедините обратное имя (т.«3010101xzmzwz»), затем отсортируйте по убыванию.Вуаля.
К настоящему моменту кто-то придумал, как сделать то же самое примерно в двух строках кода.Хотите просветить меня?
Решение
countries.sort_by do |country|
medals = country.gold + country.silver + country.bronze
[-medals, -country.gold, -country.silver, country.name]
end
Другие советы
Простой метод — использовать sort_by с произвольной форматированной строкой, например:
countries.sort_by do |c|
"%010d-%010d-%010d-%s" % [ c.gold, c.silver, c.bronze, c.name ]
end
Это преобразует все страны в сортируемый список ASCII, добавляя количество выигранных медалей к предположительно возмутительным 10 местам.Если кто-то выиграет более десяти миллиардов медалей, ваша программа может дать сбой, но это кажется разумным ограничением.
В Java вы бы реализовали сопоставимый объект для своего объекта, а затем его можно было бы легко отсортировать в ArrayList или Array.Есть ли в Ruby механизм, позволяющий сравнить два объекта «Страна»?