我有一个实例变量@limit
,它必须大于0且不大于20。我目前的代码如下:
@limit = (params[:limit] || 10).to_i
@limit = 20 if @limit > 20
@limit = 0 if @limit < 0
这看起来很丑陋。有没有更好的方法将整数限制在一定范围内?
我有一个实例变量@limit
,它必须大于0且不大于20。我目前的代码如下:
@limit = (params[:limit] || 10).to_i
@limit = 20 if @limit > 20
@limit = 0 if @limit < 0
这看起来很丑陋。有没有更好的方法将整数限制在一定范围内?
Comparable#clamp
在Ruby 2.4中可用。
3.clamp(10, 20)
=> 10
27.clamp(10, 20)
=> 20
15.clamp(10, 20)
=> 15
可以考虑使用 Enumerable#min
和 Enumerable#max
方法来实现。
例如,将值限制在0..10
的范围内:
x = 100
[[10, x].min, 0].max
# => 10
x = -2
[[10, x].min, 0].max
# => 0
x = 5
[[10, x].min, 0].max
# => 5
或者,使用Enumerable#sort
:
x = 100
[x, 0, 10].sort[1]
# => 10
x = -2
[x, 0, 10].sort[1]
# => 0
x = 5
[x, 0, 10].sort[1]
# => 5
这里有一个快速基准测试,可以展示我们应该使用哪种方法。因为总会有人说“使用sort_by
因为它比sort
更快”,所以我加了这个。只有在处理复杂对象时,sort_by
才比sort
快。 基本对象,如整数和字符串应该由sort
处理。
require 'fruity'
class Numeric
def clamp(min, max)
self < min ? min : self > max ? max : self
end
end
compare do
min_max { [[10, 100].min, 0].max }
sort { [100, 0, 10].sort[1] }
sort_by { [100, 0, 10].sort_by{ |v| v }[1] }
clamp_test { 10.clamp(0, 100) }
original {
limit = 10
limit = 100 if limit > 100
limit = 0 if limit < 0
limit
}
end
结果如下:
Running each test 65536 times. Test will take about 8 seconds.
original is faster than clamp_test by 2x ± 1.0
clamp_test is faster than sort by 6x ± 1.0
sort is faster than min_max by 2x ± 0.1
min_max is faster than sort_by by 2x ± 0.1
class Numeric
def clamp(min, max)
self < min ? min : self > max ? max : self
end
end
# usage
@limit = (params[:limit] || 10).clamp(0, 20)
为方便起见,在此提供了一个猴子补丁,用于修复在此页面的其他位置获得Tin Man基准测试胜利的“丑陋但更好”的解决方案。 (如果超出边界,它应该通过立即返回稍微快一点。)
class Numeric
def clamp(min, max)
return min if self < min
return max if self > max
self
end
end