Ruby: What's the proper syntax for a boolean r

2020-07-02 10:41发布

问题:

What is the proper syntax for a method that checks a string for a pattern, and returns true or false if the regex matches?

Basic idea:

def has_regex?(string)
    pattern = /something/i
    return string =~ pattern
end

Use case:

if has_regex?("something")
    # woohoo
else
    # nothing found: panic!
end

回答1:

If you want the put the pattern in a method, you can just do

def has_my_pattern(st)
    st =~ /pattern/
end

Or, perhaps better, put the pattern in a class variable instead?



回答2:

In the question you said:

... method that checks a string for a pattern, and returns true or false if the regex matches

As johannes pointed out String=~ returns nil if the pattern did not match and the position in the string where the matched word stared otherwise. Further he states in Ruby everything except nil and false behave like true. All of this is right.

However, they are not exactly true or false. Therefore, the last step is to coerce the value to be a Boolean. This is achieved by wrapping the result in double bangs returns a true.

def has_regex?(string)
    !!(string =~ /something/i)
end


回答3:

Your code looks fine, but you could write it even smaller.

The return value of String#=~ behaves this way:

  • nil if the pattern did not match
  • the position in the string where the matched word started

In Ruby everything except nil and false behaves like true in a conditional statement so you can just write

if string=~ pattern
  # do something
else
  # panic
end


回答4:

To make it return true/false switch the position of pattern and string and use case equality ===

def has_regex?(string)
    pattern = /something/i
    return pattern === string
end

I absolutely needed it to return true boolean value and digged around. It is actually documented in regexp class http://www.ruby-doc.org/core-2.1.3/Regexp.html#method-i-3D-3D-3D



回答5:

If you are using Ruby 2.4 or later, there are String#match?(regex) and Regexp#match?(string) methods that return booleans without the conversion shenanigans (where needed, usually not), and have improved performance to boot.

https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match-3F

https://blog.cognitohq.com/new-features-in-ruby-2-4/



回答6:

For Ruby >= 2.4 or Rails, you can do:

 regexp.match?(string)


回答7:

Adding this to the String class makes it pretty simple to use:

   class String
      def match?(regex)
          !!self.match(regex)
      end
   end

I added it to Rails initializer (RAILS_ROOT/config/initializers) and you can call directly from the string:

"Something special!".match?(/something/i) #=> true 
"Somethin' special!".match?(/something/i) #=> false 


回答8:

For anyone's future reference, double bangs are frowned upon from bbatsov's ruby style guide. Instead of using a double bang, just check if the value isn't nil. If the value isn't nil, it exists.

Instead of doing this:

def has_regex?(string)
  !!(string =~ /something/i)
end

You can always do this:

def has_regex?(string)
  !(string =~ /something/i).nil?
end


回答9:

As I wanted this to work generally, and not just for any specific project, I do not want to modify the environment at all.

I was able to get it to work by simply using the return value from the normal match method as a conditional. Tested both the positive and negative case on this sample string:

irb(main):014:0> if "123".match(/.2./); puts "worked"; end
worked
=> nil
irb(main):015:0> if "123".match(/.3./); puts "worked"; end
=> nil