假设您有一组跑步者:
runners = [al, betty, chris, debby]
你有一个方法time
,可以在比赛中返回跑步者的时间。
如果time
方法总是返回一个浮点数,我知道您可以使用sort_by
按时按顺序对运行者进行排序,如下所示:
runners.sort_by do |runner|
runner.time
end
但是,假设time
有时返回一个字符串,比如"disqualified"
。在那种情况下,你会如何按时间对跑步者进行排序,不合格的跑步者会持续多久?如果你想让不合格的跑步者先或在其他位置上怎么办?
答案 0 :(得分:5)
这是一个简单的方法。在数组中只有两个排序字段,Ruby将按第一个标准排序,然后按第二个标准排序。
runners.sort_by do |runner|
[(runner.time == 'disqualified') ? 1 : 0, runner.time]
end
此处1
将在0
之后排序,因此取消资格的次数将持续到位。
答案 1 :(得分:1)
您可以为此创建自定义类:
class RunningTime
attr_reader :time
def initialize time
@time = time
end
def disqualified?
@time == 'disqualified'
end
def <=> rhs
case [disqualified?, rhs.disqualified?]
when [false, true]
-1
when [true, true]
0
when [true, false]
1
else
time <=> rhs.time
end
end
end
runners.sort_by {|runner| RunningTime.new(runner.time)}
答案 2 :(得分:0)
回归时间是Object.time.to_f
吗?如果是这样,在String上调用to_f将返回0.0。如果没有,请尝试在块中调用runner.time.to_f。 String类型的所有时间值都是0.0。
答案 3 :(得分:0)
你可以这样做:
[5,4,"disqualified",2,7].sort_by { |x| x.kind_of?(String) ? Float::INFINITY : x }
#=> [2, 4, 5, 7, "disqualified"]
在Ruby&lt; 1.9没有Float::INFINITY
,但你可以通过Inf = 1.0 / 0
来获取它。
答案 4 :(得分:0)
假设您的跑步者来自数据库,使用单独的字段/方法检查不合格的跑步者,您可以将排序逻辑推送到数据库层,这比将所有记录加载到内存和放大器中更快。用红宝石分类。