如何在Ruby中限制整数的范围

20

我有一个实例变量@limit,它必须大于0且不大于20。我目前的代码如下:

@limit = (params[:limit] || 10).to_i
@limit = 20 if @limit > 20
@limit = 0 if @limit < 0

这看起来很丑陋。有没有更好的方法将整数限制在一定范围内?

6个回答

32

Comparable#clamp在Ruby 2.4中可用

3.clamp(10, 20)
=> 10

27.clamp(10, 20)
=> 20

15.clamp(10, 20)
=> 15

19

可以考虑使用 Enumerable#minEnumerable#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

排序解决方案也非常出色,我认为更易于阅读。 - superluminary

9

这里有一个快速基准测试,可以展示我们应该使用哪种方法。因为总会有人说“使用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

有时候丑陋更好。

这真的看起来像是性能瓶颈吗? - John Ledbetter
1
这取决于使用它的代码。如果调用这种算法几十万次,时间就会累加。知道最快的方法总是一个好主意,这样我们就可以平衡速度、可读性和代码风格。 - the Tin Man
有时候丑陋更好。我喜欢它! :) - Navaneeth

6
如果你想要猴子补丁一个方法,你可以像这样做:
class Numeric
  def clamp(min, max)
    self < min ? min : self > max ? max : self
  end
end

# usage
@limit = (params[:limit] || 10).clamp(0, 20)

1
夹紧(Clamp)是一个非常棒的方法名。 - superluminary
我搜索了“constrain”,但惊讶地发现它没有内置。 - jchook

2

为方便起见,在此提供了一个猴子补丁,用于修复在此页面的其他位置获得Tin Man基准测试胜利的“丑陋但更好”的解决方案。 (如果超出边界,它应该通过立即返回稍微快一点。)

class Numeric
  def clamp(min, max)
    return min if self < min
    return max if self > max
    self
  end
end

-3

(1..19).cover? @limit

详见文档


2
有用的方法,但不能解决将整数锁定在范围内的问题。 - superluminary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接