2010-02-09 172 views
3

我正在构建一个小工具来显示奥运奖牌数。我有一个“国家”对象的集合,每个对象都有一个“名称”属性,以及“金牌”,“银牌”,“铜牌”的奖牌数量。按数字排序(最高优先),然后按字母排序(按字母顺序排列)

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

我在做这个红宝石,但我认为语言无所谓。我确实找出了一个解决方案,但是如果觉得必须有更加优雅的方式来做到这一点。

这里就是我所做的:

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

  2. 既然我们想按照最高的奖牌数排序,那么排序是DESC。但是之后我们想按字母顺序进行分类(即ASC)。所以我创建了一个函数,可以将一个单词反转(即“加拿大”=>“xzmzwz”)

  3. 将加权合计转换为字符串,concat反相名称(即“3010101xzmzwz”),然后降序排序。瞧。

到目前为止,有人已经想出了如何在大约2行代码中做同样的事情。照顾开导我?

回答

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

这是特定于某个Ruby版本吗?它似乎不适合我。 – Beanish 2010-02-09 21:33:45

+0

它不应该。它适用于1.8.7和1.9,我没有看到为什么它不适用于1.8.6。 'sort_by'绝对存在于1.8.6中,'Array#<=>'也是如此。 – sepp2k 2010-02-09 21:36:57

+0

请注意,'sort_by'不就地排序。 – sepp2k 2010-02-09 21:37:46

1

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

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

这通过填充奖牌数赢得了大概所有国家转换到一个ASCII排序列表离谱的10个地方。如果有人获得了超过100亿的奖牌,你的程序可能会出现故障,但这似乎是一个合理的限制。

+0

对于“合理约束”:-)但是,请注意,由于情况完全不受控制,合理的约束有时会变得不合理:http://Blog.BusinessOfSoftware.Org/2009/01/bos- digest --- when-good-assumptions-go-bad.html – 2010-02-09 23:00:16

+0

只有在津巴布韦,你需要一个Bignum来代表你的银行账户余额。 – tadman 2010-02-10 00:58:13

+0

我不相信这解决了我原来的一个要求 - 奖牌数应该按降序排列(最大的第一个),但按字母排序的子排序应该是升序(最小或a..z)。 因此,按“---”排序将首先排序最小数量的奖牌。首先是最大的奖牌,然后是按照字母顺序排序的国家。的奖牌。 – dlehman 2010-02-10 01:16:02

0

在Java中,您可以在您的对象上实现可比较的功能,然后它可以很容易地在ArrayList或Array中排序。 Ruby中是否有一种机制来告诉如何比较两个“国家”对象?