I need to write a regex in Ruby that returns true / false

6.7k views Asked by At

I am trying to write a regex that takes a word and returns true for words starting with a vowel and returns false for words starting with a consonant. I have never written regex before, and I'm a little confused on how to write the expression. This is what I have so far:

def starts_with_a_vowel?(word)
  if word.match(/\A+[aeiou]/) == true
    return true
  else
    return false  
  end
end

Edit: So if word = "boat" , expression should return false. If word = "apple", expression should return true.

6

There are 6 answers

2
n0rph3u5 On BEST ANSWER

EDIT:

OK.. So.. I never tested the code I formerly wrote.. it was meant only as some suggestion how to use the match with regex, but it not worked at all.. (that code snippet is now attached to the end of my answer fyi)

this here should be the working one:

def starts_with_a_vowel?(word)
  !!word.capitalize.match(/\A+[AEIOU]/)
end

..but how it was mentioned by Eric Duminil here below in comments, the method/function is not needed

!!word.capitalize.match(/\A+[AEIOU]/) can be used directly.. it returns true or false

but there are surely other (maybe better) solutions too..

..and here is the NOT working code, which I formerly wrote:

def starts_with_a_vowel?(word)
  return word.match(/\A+[aeiou]/).length > 0
end

..the match method returns nil when not match and because nil has no length method defined, it raises NoMethodError

0
Mark Reed On

You're doing a lot of extra work for no reason. First, you don't need to check for equality with true; just if *expression* does the trick.

But in this case you don't need if at all. A regex match already returns a value that can be interpreted as a Boolean. =~ returns the index of the match as an integer (which is "truthy"); String#match returns a MatchData object (which is also truthy). Everything in Ruby is truthy except false and nil, and nil is what both =~ and String#match return if there's no match. So all you have to do is turn the result of one of those into the corresponding Boolean value, which you can do with !!. For example:

def starts_with_a_vowel? word
  !!(word =~ /^[aeiou]/)
end

That !! is read "not not", by the way. The ! operator by itself treats its argument as Boolean and returns its opposite as an actual Boolean; that is !(some truthy value) returns false (not nil), and !(some falsey value) returns true (not just some truthy value). So applying ! twice turns any truthy value into true and any falsey value (false or nil) into false.

3
Eric Duminil On

In Ruby, you almost never need anything to return true or false. For boolean logic and if/case/unless statements, truthy/falsey are good enough. Also, don't forget to use case-insensitive Regex (with //i). A is a vowel :

class String
  def starts_with_a_vowel?
    self =~ /\A[aeiou]/i
  end
end

if "Airplane".starts_with_a_vowel?
  puts "Indeed"
end
#=> "Indeed"

If for some reason you really need true/false :

class String
  def starts_with_a_vowel?
    !(self =~ /\A[aeiou]/i).nil?
  end
end
2
Michael Kohl On

Do you have to use a regular expression? Just asking cause Ruby already provides String#start_with?

vowels = %w(a e i o u)
"boat".start_with?(*vowels)
# => false
"apple".start_with?(*vowels)
#=> true
1
Cary Swoveland On

Here are a couple of ways to do this.

#1

word = 'Ahoy'
!!(word[0] =~ /[aeiou]/i)
  #=> true
word = 'hiya'
!!(word[0] =~ /[aeiou]/i)
  #=> false

The regex reads, "match a vowel, case indifferently (/i)". !! converts a thruthy value to true and a falsy value (nil or false) to false:

!!0 = !(!0) = !(false) = true
!!nil = !(!nil) = !(true) = false

#2

word = 'Ahoy'
(word[0] =~ /[aeiou]/i) ? true : false
  #=> true
word = 'hiya'
(word[0] =~ /[aeiou]/i) ? true : false
  #=> false
0
DarkWiiPlayer On

word.match? /\A[aeiou]/i is literally all you need. (ruby >= 2.4)

It matches the beginning of the string \A followed by a vowel [aeiou] in a case-insensitive manner i returning a bool word.match?

Before ruby 2.4 you have to use word.match and convert it to a bool, which is easiest done by logically negating it twice with !!