I want to know what's the best way to make the String.include?
methods ignore case. Currently I'm doing the following. Any suggestions? Thanks!
a = "abcDE" b = "CD" result = a.downcase.include? b.downcase
Edit: How about Array.include?
. All elements of the array are strings.
case insensitive (not comparable) (computer science) Treating or interpreting upper- and lowercase letters as being the same.
The in_array() function searches an array for a specific value. Note: If the search parameter is a string and the type parameter is set to TRUE, the search is case-sensitive.
indexOf(someStr. toLowerCase()); That will do a case insensitive indexOf() .
Note: The includes() method is case sensitive i.e, it will treat the Uppercase characters and Lowercase characters differently.
If you are only going to test a single word against an array, or if the contents of your array changes frequently, the fastest answer is Aaron's:
array.any?{ |s| s.casecmp(mystr)==0 }
If you are going to test many words against a static array, it's far better to use a variation of farnoy's answer: create a copy of your array that has all-lowercase versions of your words, and use include?
. (This assumes that you can spare the memory to create a mutated copy of your array.)
# Do this once, or each time the array changes downcased = array.map(&:downcase) # Test lowercase words against that array downcased.include?( mystr.downcase )
Even better, create a Set
from your array.
# Do this once, or each time the array changes downcased = Set.new array.map(&:downcase) # Test lowercase words against that array downcased.include?( mystr.downcase )
My original answer below is a very poor performer and generally not appropriate.
Following are benchmarks for looking for 1,000 words with random casing in an array of slightly over 100,000 words, where 500 of the words will be found and 500 will not.
any?
.any?
from my comment.Set
from the array of downcased strings, once before testing. user system total real regex 18.710000 0.020000 18.730000 ( 18.725266) casecmp 5.160000 0.000000 5.160000 ( 5.155496) downarray 16.760000 0.030000 16.790000 ( 16.809063) downonce 0.650000 0.000000 0.650000 ( 0.643165) set_once 0.040000 0.000000 0.040000 ( 0.038955)
If you can create a single downcased copy of your array once to perform many lookups against, farnoy's answer is the best (assuming you must use an array). If you can create a Set
, though, do that.
If you like, examine the benchmarking code.
I (originally said that I) would personally create a case-insensitive regex (for a string literal) and use that:
re = /\A#{Regexp.escape(str)}\z/i # Match exactly this string, no substrings all = array.grep(re) # Find all matching strings… any = array.any?{ |s| s =~ re } # …or see if any matching string is present
Using any?
can be slightly faster than grep
as it can exit the loop as soon as it finds a single match.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With