0

I learned Rails and now would like to expand my knowledge of Ruby. So I'm doing some C++ exercises in Ruby. Specifically I need to find if a substring exists in a string. If it does I need it to return its starting index. If it doesn't exist have it return -1. I came up with a Ruby solution that's very similar to C++ and was wondering if there's a "better", more idiomatic solution in Ruby?

C++

int find(char str[], char sub_str[])
{
  int str_length = strlen(str);
  int sub_str_length = strlen(sub_str);
  bool match = false;

  for(int i=0; i<str_length; i++)
  {
    if(str[i] == sub_str[0])
    {
      for(int j=1; j<sub_str_length; j++)
      {
        if(str[i+j] == sub_str[j])
          match = true;
        else
        {
          match = false;
          break;
        }
      }
      if(match)
        return i;
    }
  }
  return -1;
}

Ruby

def find_sub_str(str, sub_str)
  match = false
  for i in 0...str.length
    if str[i] == sub_str[0]
      for j in 1...sub_str.length
        if str[i+j] == sub_str[j]
          match = true
        else
          match = false
          break
        end
      end
      if match == true
        return i
      end
    end
  end
  return -1
end
4

3 回答 3

4

您可以使用索引方法String。它nil在匹配失败时返回,这比返回 -1 更符合 Ruby 的习惯。

 "SubString".index("String") # -> 3
 "SubString".index("C++") # -> nil

如果你真的想要这种行为,你可以将它包装在一个返回 -1 的测试中。

于 2013-07-15T21:02:15.577 回答
2
  1. 不要for在 Ruby 中使用,它只是调用each而不引入范围。就这样for i in 0...str.length变成了(0...str.length).each do |i|

  2. 高阶函数是你的朋友!使用each_cons&find_index让事情变得更干净(研究Enumerable,它是许多有用方法的所在地):

    def find_sub_str(str, sub_str)
      str.chars.each_cons(sub_str.length).find_index do |s|
        s.join == sub_str
      end
    end
    
    find_sub_str('foobar', 'ob')  #=> 2
    
  3. 只需使用 Ruby 核心的:index :)

    'foobar'.index('ob')  #=> 2
    

当没有匹配项时, #2 和 #3 都返回nil, not 。-1这是最好的,因为nil在 Ruby 中是错误的。

于 2013-07-15T21:06:25.413 回答
0
#how if we use this solution, it gets the job done in O(n)    

given_string = "Replace me with your code!"

chars_given_string = given.split('')

chars_of_substr = "ith".split('')

is_substr = false
ptr = 0

char_given.each do |i|
    if ( i == substr[ptr])
       ptr += 1
    else
       ptr = 0
    end
    is_substr = true if ptr == substr.length
    break if ptr == substr.length
end

puts is_substr
于 2014-02-16T09:17:14.873 回答