检查某个字母在字符串

时间:2015-07-26 23:36:29

标签: ruby regex string

我正在解决Coderbyte问题,遇到一个名为ABCheck的问题,如果字母“a”和b分开三个位置,它会接受一个字符串并返回true。我知道有一种更简单的方法可以用正则表达式做到这一点,但我试图以逻辑方式首先进行,以用于学习目的。

这是我的代码:

def ABCheck(str)
  str = str.downcase.split('')
  str.each_with_index do |char,index|
    if char == 'a' && str[index+4] == 'b'
      return "true"
    elsif 
    char == 'b' && str[index+4] == 'a'
      return "true"
    else
      return "false"
    end
  end
end

ABCheck("Laura sobs")

我的代码没有返回正确的答案。即使答案应为false,它也会返回true

2 个答案:

答案 0 :(得分:2)

问题是您只检查第一个字符 - 如果第一个字符不是ab符合搜索条件,则会立即返回"false"。在知道没有匹配的位置之前,您需要在所有中搜索字符串中的可能位置。

(这是在某种集合中搜索匹配时的常见模式;如果您找到它,您可以立即返回,但如果不这样做,则必须继续搜索直到结束。)

另请注意,您返回字符串 "false",而不是布尔值false

示例解决方案(没有正则表达式):

def axb_match?(str, in_between = 3)
  distance = in_between + 1 # chars in between + the 'b'
  str, i = str.downcase, -1
  while i = str.index('a', i + 1)
    return true if (str[i + distance] == 'b') || (i >= distance && str[i - distance] == 'b')
  end
  false # no match was found (finding would return immediately)
end
axb_match? "Laura sobs" # -> true

当然,使用正则表达式非常简单:

str =~ /(a...b)|(b...a)/i

答案 1 :(得分:2)

由于@Arkku诊断出您的问题,我将把我的评论限制在非正则表达式解决方案的替代方法中。 (在现实生活中,你当然希望使用正则表达式。)

我认为Ruby方式是使用Enumerable#each_cons而不是索引:

def a3b_match?(str)
  str.each_char.each_cons(5).any? { |f,*_,l|
    (f=='a' && l=='b') || (f=='b' && l=='a') }
end

a3b_match?('xadogbite')   #=> true
a3b_match?('xbdogaite')   #=> true
a3b_match?('xbdgaite')    #=> false
a3b_match?('xadoggybite') #=> false

如果您想要匹配的数量,请将Enumerable#any?更改为Enumerable#count

以下是步骤:

str = 'xadogbite'
enum0 = str.each_char
  #=> #<Enumerator: "xadogbite":each_char> 
enum1 = enum0.each_cons(5)
  #=> #<Enumerator: #<Enumerator: "xadogbite":each_char>:each_cons(5)>

仔细检查枚举器enum0enum1计算的返回值。您可以将enum1视为&#34;化合物&#34;枚举器。

通过将该枚举器转换为数组,我们可以看到enum1 any?将传递到块中的({1}}值:

enum1.to_a
  #=> [["x", "a", "d", "o", "g"],
  #    ["a", "d", "o", "g", "b"],
  #    ["d", "o", "g", "b", "i"],
  #    ["o", "g", "b", "i", "t"],
  #    ["g", "b", "i", "t", "e"]] 

让我们模拟将enum1的第一个值传递到块中并将其分配给块变量 1

f,*m,l = enum1.next
f #=> "x" 
m #=> ["a", "d", "o"]
l #=> "g" 

然后我们执行块计算:

(f=='a' && l=='b') || (f=='b' && l=='a') }
  #=> ('x'=='a' && 'g'=='b') || ('x'=='b' && 'g'=='a') }
  #=> false || false => false
因此,

any?必须将enum1的下一个元素传递到块中:

 f,*_,l = enum1.next
   #=> ["a", "d", "o", "g", "b"]
 f #=> "a"
 l #=> "b"

(f=='a' && l=='b') || (f=='b' && l=='a') }
  #=> ('a'=='a' && 'b'=='b') => true

由于我们在(f=='a' && l=='b')上匹配,因此Ruby无需评估(f=='b' && l=='a')或对enum1的其他元素执行类似的计算,因此她没有&# 39;吨。 any?会返回true

1我使用局部变量m而不是_,因为IRB将后者用于自己的目的。从命令行运行时,_工作正常。