Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive regex matching in Ruby

Tags:

regex

ruby

I have an array with a list of power rangers colors, rangers = ["red", "blue", "yellow", "pink", "black"]

I want to validate if a given argument matches the power rangers colors, but the problem is the argument may come in different case (uppercase, lowercase, mix).

Example:

def validate_rangers(color)
  rangers = ["red", "blue", "yellow", "pink", "black"]
  rangers.grep(color).any?
end

validates_rangers("red") #=> true

but

validates_rangers("Red") #=> false. Needs to be true.

How can I use case insensitive grep?

like image 886
Iggy Avatar asked Nov 27 '22 20:11

Iggy


2 Answers

You can use the insensitive flag:

rangers.grep(/#{color}/i).any?

Since the flag makes the regex insensitive, it will match whatever case in red

Working demo

def validate_rangers(color)
  rangers = ["red", "blue", "yellow", "pink", "black"]
  rangers.grep(/#{color}/i).any?
end
like image 114
Federico Piazza Avatar answered Dec 05 '22 18:12

Federico Piazza


The more idiomatic Ruby way of solving this problem looks like this:

# Define a constant that defines the colors once and once only.
RANGERS = ["red", "blue", "yellow", "pink", "black"]

def validates_rangers(color)
  # Check against an arbitrary object that may or may not be a string,
  # and downcase it to match better.
  RANGERS.include?(color.to_s.downcase)
end

If you're doing this frequently you might want to use a Set to optimize performance:

RANGERS = Set.new(["red", "blue", "yellow", "pink", "black"])

That doesn't require any code changes, but lookups are considerably faster.

If you're intent on using a regular expression:

# Construct a case-insensitive regular expression that anchors to the
# beginning and end of the string \A...\z
RANGERS = Regexp.new(
  '\A(?:%s)\z' % Regexp.union("red", "blue", "yellow", "pink", "black"),
  Regexp::IGNORECASE
)

def validates_rangers(color)
  # Double negation returns true/false instead of MatchData
  !!RANGERS.match(color.to_s.downcase)
end

validates_rangers("Red")
# => true
validates_rangers("dred")
# => false
like image 33
tadman Avatar answered Dec 05 '22 17:12

tadman