按数字(最高优先)然后按字母(字母顺序)对对象集合进行排序
Posted
技术标签:
【中文标题】按数字(最高优先)然后按字母(字母顺序)对对象集合进行排序【英文标题】:Sort a collection of objects by number (highest first) then by letter (alphabetical) 【发布时间】:2011-01-15 00:06:45 【问题描述】:我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及用于奖牌数量的“金”、“银”、“铜”。
列表应该排序: 1.首先按奖牌总数 2.如果奖牌相同,按类型进行分类(金>银>铜,即两金>一金+一银) 3.如果奖牌和类型相同,按字母顺序排序
我正在用 ruby 做这个,但我想语言并不重要。我确实想出了一个解决方案,但如果觉得必须有一个更优雅的方法来做到这一点。
这就是我所做的:
使用加权奖牌总数创建一个虚拟属性。因此,如果他们有 2 枚金币和 1 枚银币,加权总数将为“3.020100”。 1金1银1铜就是“3.010101”
由于我们要将奖牌数排序为最高,因此列表按 DESC 排序。但是之后我们想要按字母顺序(即 ASC)进行子排序。所以我创建了一个函数,可以对一个单词进行 alpha 反转(即“canada”=>“xzmzwz”)
将加权总数转换为字符串,连接反向名称(即“3010101xzmzwz”),然后降序排序。瞧。
到目前为止,有人已经弄清楚了如何用大约 2 行代码来做同样的事情。愿意开导我吗?
【问题讨论】:
【参考方案1】:countries.sort_by do |country|
medals = country.gold + country.silver + country.bronze
[-medals, -country.gold, -country.silver, country.name]
end
【讨论】:
这是特定于某个 Ruby 版本的吗?它似乎对我不起作用。 不应该。它在 1.8.7 和 1.9 上适用于我,而且我看不出它不应该在 1.8.6 上运行的任何理由。sort_by
肯定存在于 1.8.6 中,Array#<=>
也是如此。
请注意,sort_by
不会就地排序。【参考方案2】:
一个简单的方法是将 sort_by 与一些任意格式的字符串一起使用,例如:
countries.sort_by do |c|
"%010d-%010d-%010d-%s" % [ c.gold, c.silver, c.bronze, c.name ]
end
这会将所有国家/地区转换为 ASCII 可排序列表,方法是将赢得的奖牌数量填充到可能令人发指的 10 位。如果有人赢得超过 100 亿枚奖牌,您的程序可能会出现故障,但这似乎是一个合理的限制。
【讨论】:
+1 表示“合理的约束” :-) 但是,请注意,由于完全无法控制的情况,合理的约束有时会变得不合理:Blog.BusinessOfSoftware.Org/2009/01/… 只有在津巴布韦,您才需要 Bignum 来代表您的银行账户余额。 我不相信这能解决我最初的要求——奖牌数应该按降序排序(最大的在前),但字母顺序的子排序应该是升序的(最小的,或.. z)。因此,按“在 Java 中,您可以在对象上实现可比较,然后可以轻松地将其排序到 ArrayList 或 Array 中。 Ruby 中是否有一种机制可以告诉您如何比较两个“国家”对象?
【讨论】:
以上是关于按数字(最高优先)然后按字母(字母顺序)对对象集合进行排序的主要内容,如果未能解决你的问题,请参考以下文章