Suppose you have an array of runners:
假设你有一组跑步者:
runners = [al, betty, chris, debby]
And you have a method time
that returns the runners time in the race.
你有一个方法时间返回赛跑者的时间。
In the case that the time
method always returns a float, I know that you can sort the runners by there times using sort_by
as follows:
如果时间方法总是返回一个浮点数,我知道您可以使用sort_by对跑步者进行排序,如下所示:
runners.sort_by do |runner|
runner.time
end
However, suppose that time
sometimes returned a string, say "disqualified"
. In that case, how would you sort the runners by time, with the disqualified runners last? What if you wanted the disqualified runners first or in some other position?
然而,假设时间有时返回一个字符串,说“取消资格”。在这种情况下,你如何按时间对跑步者进行排序,最后是不合格的跑步者?如果你想让那些不合格的运动员先跑还是换别的位置呢?
5 个解决方案
#1
5
Here's a simple way. Just have two sort fields in an array, and Ruby will sort by the first criterion and then the second.
这是一个简单的方法。在数组中有两个排序字段,Ruby按第一个标准排序,然后第二个。
runners.sort_by do |runner|
[(runner.time == 'disqualified') ? 1 : 0, runner.time]
end
Here 1
will be sorted after 0
, so disqualified times will come last.
这里的1将在0之后排序,因此不合格的时间将是最后一次。
#2
1
You could create a custom class for this:
您可以为此创建一个自定义类:
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)}
#3
0
Is time returning Object.time.to_f
? If so, calling to_f on a String will return 0.0. If not, try calling runner.time.to_f in the block. All time values of type String will be 0.0.
是时候返回Object.time.to_f吗?如果是,在字符串上调用to_f将返回0.0。如果没有,试着打个电话。to_f块。字符串类型的所有时间值都是0。
#4
0
You could do it analogous to this:
你可以做类似的事情
[5,4,"disqualified",2,7].sort_by { |x| x.kind_of?(String) ? Float::INFINITY : x }
#=> [2, 4, 5, 7, "disqualified"]
In Ruby < 1.9 there is no Float::INFINITY
, but you can get it by doing Inf = 1.0 / 0
.
在Ruby < 1.9中没有Float::INFINITY,但是你可以通过Inf = 1.0 / 0得到它。
#5
0
Assuming that you're runners come from a database, using a separate field / method for checking for disqualified runners lets you push the sorting logic into the database layer, which will be faster than loading all of the records into memory & sorting them in ruby.
假设您是来自数据库的运行程序,使用一个单独的字段/方法检查不合格的运行程序,您可以将排序逻辑推入数据库层,这比将所有记录加载到内存中并在ruby中对它们进行排序要快得多。
#1
5
Here's a simple way. Just have two sort fields in an array, and Ruby will sort by the first criterion and then the second.
这是一个简单的方法。在数组中有两个排序字段,Ruby按第一个标准排序,然后第二个。
runners.sort_by do |runner|
[(runner.time == 'disqualified') ? 1 : 0, runner.time]
end
Here 1
will be sorted after 0
, so disqualified times will come last.
这里的1将在0之后排序,因此不合格的时间将是最后一次。
#2
1
You could create a custom class for this:
您可以为此创建一个自定义类:
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)}
#3
0
Is time returning Object.time.to_f
? If so, calling to_f on a String will return 0.0. If not, try calling runner.time.to_f in the block. All time values of type String will be 0.0.
是时候返回Object.time.to_f吗?如果是,在字符串上调用to_f将返回0.0。如果没有,试着打个电话。to_f块。字符串类型的所有时间值都是0。
#4
0
You could do it analogous to this:
你可以做类似的事情
[5,4,"disqualified",2,7].sort_by { |x| x.kind_of?(String) ? Float::INFINITY : x }
#=> [2, 4, 5, 7, "disqualified"]
In Ruby < 1.9 there is no Float::INFINITY
, but you can get it by doing Inf = 1.0 / 0
.
在Ruby < 1.9中没有Float::INFINITY,但是你可以通过Inf = 1.0 / 0得到它。
#5
0
Assuming that you're runners come from a database, using a separate field / method for checking for disqualified runners lets you push the sorting logic into the database layer, which will be faster than loading all of the records into memory & sorting them in ruby.
假设您是来自数据库的运行程序,使用一个单独的字段/方法检查不合格的运行程序,您可以将排序逻辑推入数据库层,这比将所有记录加载到内存中并在ruby中对它们进行排序要快得多。