Ruby 测试范围内的数字,特定值除外

Ruby 测试范围内的数字,特定值除外,ruby,Ruby,我想测试一个数字n是否在1到26的范围内,除了有重复数字的值(所以11,22): 有没有比这样做更好的方法: [*1..10, *12..21, *23..26].include?(n) [*1..10, *12..21, *23..26].include?(n) 有没有比这样做更好的方法: [*1..10, *12..21, *23..26].include?(n) [*1..10, *12..21, *23..26].include?(n) 当然可以。从简单的部分组成复杂的检查。第一

我想测试一个数字
n
是否在1到26的范围内,除了有重复数字的值(所以11,22):

有没有比这样做更好的方法:

[*1..10, *12..21, *23..26].include?(n)
[*1..10, *12..21, *23..26].include?(n)
有没有比这样做更好的方法:

[*1..10, *12..21, *23..26].include?(n)
[*1..10, *12..21, *23..26].include?(n)
当然可以。从简单的部分组成复杂的检查。第一部分检查范围,另一部分拒绝重复数字的数字

n.between?(1, 26) && !has_repeated_digits?(n)
其中,重复数字的检查可以如下实现:

def has_repeated_digits?(n)
  n.to_s.chars.uniq != n.to_s.chars

  # or, in newer rubies (2.4+)
  n.digits.uniq != n.digits
end

或者,您可以交换一些RAM以避免计算,并将所有“无效”数字存储在
集合中。您可以根据自己的意愿进行更改,而无需触摸原始条件。抽象之美。

创建一个散列。用要跳过的数字填充哈希。并检查存在键:

a = [11, 22]
h = Hash[a.map {|x| [x, 1]}]
n=24

n.between?(1, 26) && !h.key?(n)
稍微短一点:

a=(1..26).to_a - [11,22]
然后,使用
include?
方法


(请注意,它将删除所有引用)

如果范围像您的情况一样有限且精确,则说明您做得很好。更好的方法是减法

([*1..26] - [11, 22]).include?(n=11)
其他方法肯定会更好,但除了比用例所需的计算量更多之外,没有任何好处

正如注释中所述,数组构建也很昂贵,如果您在应用程序中定义了
常量
全局变量
的概念,那么您可以在初始化过程中定义常量,如下所示:

ARRAY_RANGE = [*1..26] - [11, 22]
当您需要检查时,您只需:

ARRAY_RANGE.include?(n=11)

数组查找为O(N)。而且构建阵列也不是免费的。但对于像这样的微小阵列,这可能没什么大不了的。@SergioTulentsev完全正确!由于定义的范围很短,因此可以忽略不计。使用
Set
而不是数组可以大大提高性能。O(1)查找FTW:)我明白了,你能举例说明吗@SergioTulentsev对于这种散列,您不关心值,只关心键的存在,从语义上讲,最好使用
Set
@SergioTulentsev:Plot twist:Ruby只是一个散列,我们不关心值。:)我明白你的意思。@EricDuminil:是的,我知道。我说“语义更好”:)建议分解检查肯定会让它更可读,谢谢!此外,在本例中,22也不应该通过检查。@SergioTulentsev它不应该通过检查<代码>22。介于?(1,26)和&!(22%100%11)。零?#=>false
我认为这是所有解决方案中速度最快、内存效率最高的解决方案。但有一个严重的限制:)这个问题可能还不清楚。我解释说OP希望排除具有重复的最低两位数。如果OP仅仅意味着在任何位置重复连续的数字,那么这不是我的答案想要做的。甚至可能不是连续的。比如303。虽然是的,但我不知道这个问题的制约因素。