按编号(最高的第一个)然后按字母(按字母顺序)对对象的集合进行排序

时间:2010-02-09 20:59:05

标签: ruby arrays sorting enumerable

我正在构建一个小部件来显示奥运会的奖牌数量。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,而“金”,“银”,“青铜”用于奖牌计数。

列表应该排序: 1.首先是总奖牌数 2.如果相同的奖牌,按类型分类(金>银>青铜,即两金> 1金+ 1银) 3.如果奖牌和类型相同,则按字母顺序排序

我在ruby中这样做,但我认为语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方式来做到这一点。

这就是我的所作所为:

  1. 使用加权奖牌总额创建虚拟属性。因此,如果他们有2金和1银,加权总数将是“3.020100”。 1金,1银和1铜将是“3.010101”

  2. 由于我们希望将奖牌计数排在最前面,因此列表是按DESC排序的。但是之后我们想要按字母顺序(即ASC)进行子排序。所以我创建了一个字母反转单词的函数(即“canada”=>“xzmzwz”)

  3. 将加权总数转换为字符串,将反转名称连接起来(即“3010101xzmzwz”),然后按降序排序。瞧。

  4. 到目前为止,有人已经想出如何在大约2行代码中做同样的事情。关心赐教?

3 个答案:

答案 0 :(得分:10)

countries.sort_by do |country|
  medals = country.gold + country.silver + country.bronze
  [-medals, -country.gold, -country.silver, country.name]
end

答案 1 :(得分:1)

一个简单的方法是使用sort_by和一些任意格式的字符串,例如:

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

这会将所有国家/地区转换为ASCII可排序列表,方法是将赢得的奖牌数量填充到可能令人难以置信的10个位置。如果有人赢得超过100亿枚奖牌,你的节目可能会出现故障,但这似乎是一个合理的限制。

答案 2 :(得分:0)

在Java中,您可以在对象上实现可比性,然后可以轻松地在ArrayList或Array中进行排序。 Ruby中是否有一种机制来告诉你如何比较两个“Country”对象?