2017-05-08 46 views
0

我想测试一个数范围为1内n下降到26,但对于已经重复数字的值(因此11,22):试验在范围数目,除了某些值

(n=24).between?(1, 26) # => true, ok 
(n=1).between?(1, 26) # => true, ok 
(n=11).between?(1, 26) # => true (but I want this to return false) 

有没有更好的方式来实现这一目标不是做:

[*1..10, *12..21, *23..26].include?(n) 

回答

4

有没有更好的方式来实现这一目标不是做:

[*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 

或者,你可以牺牲一些内存,以避免在计算和存储所有你的“无效”数字在Set或其他东西。您可以根据需要更改此设置,并且不需要触摸原始状态。抽象的美。

+0

建议打破支票必将使其更具可读性,谢谢! – FloatingRock

0

创建一个散列。用数字填充散列以跳过。并检查所有脑干键:

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

n.between?(1, 26) && !h.key?(n) 
+0

对于这样的散列,如果你不关心值,只有键存在,它在语义上更好使用'Set'。 –

+1

@SergioTulentsev:Plot twist:Ruby的['Set'](http://ruby-doc.org/stdlib-2.4.1/libdoc/set/rdoc/Set.html)只是一个哈希,我们不会关心价值。 :)我确实明白你的观点。 –

+2

@EricDuminil:是的,我知道。我说“_semantically_ better”:) –

0

短一点:

a=(1..26).to_a - [11,22] 

然后,使用include?方法。

(请注意,它会删除所有实例)

2

如果范围是有限的,精确的为你的情况,你正在做的不错。一个更好的方法是减法。

([*1..26] - [11, 22]).include?(n=11) 

其他方法肯定会更好,但不会超过您的用例所需的更多计算。

正如评论,阵列建筑太昂贵,如果你在你的应用程序中定义的constantsglobal variables一个概念,那么你可以像下面的初始化过程中定义常量:

ARRAY_RANGE = [*1..26] - [11, 22] 

当你必须检查,你只需要:

ARRAY_RANGE.include?(n=11) 
+1

数组查找是O(N)。并且构建阵列也不是免费的。但对于这样的小型数组,这可能并不重要。 –

+0

@SergioTulentsev到底!由于范围被定义并且很短,因此可以忽略不计。 –

+0

通过使用'Set'而不是数组可以大大提高性能。 O(1)查找FTW :) –

1
24.between?(1, 26) && !(24%100%11).zero? # => true 
1.between?(1, 26) && !(1%100%11).zero? # => true 
11.between?(1, 26) && !(11%100%11).zero? # => false 
22.between?(1, 26) && !(22%100%11).zero? # => false 
+0

另外,在这个例子中,22也不应该通过支票。 –

+0

@SergioTulentsev它没有。 '22. between?(1,26)&&!(22%100%11).zero? #=>假' – sawa

+0

啊,的确,我愚蠢。 –