你如何在ruby中对多种类型进行排序?

时间:2011-08-06 17:24:13

标签: ruby sorting

假设您有一组跑步者:

runners = [al, betty, chris, debby]

你有一个方法time,可以在比赛中返回跑步者的时间。

如果time方法总是返回一个浮点数,我知道您可以使用sort_by按时按顺序对运行者进行排序,如下所示:

runners.sort_by do |runner|
    runner.time
end

但是,假设time有时返回一个字符串,比如"disqualified"。在那种情况下,你会如何按时间对跑步者进行排序,不合格的跑步者会持续多久?如果你想让不合格的跑步者先或在其他位置上怎么办?

5 个答案:

答案 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)

假设您的跑步者来自数据库,使用单独的字段/方法检查不合格的跑步者,您可以将排序逻辑推送到数据库层,这比将所有记录加载到内存和放大器中更快。用红宝石分类。