Reputation:
How can I tell if my string contains a substring from an array?
I thought include?
was the key, but apparently not ...
arr = ["aa", "bb", "cc"]
str = "mystringcc"
str.include?(*arr)
ArgumentError: wrong number of arguments (given 3, expected 1)
In the above example, I would expect the result to be true
since the string has "cc"
, which is an element of the array.
Upvotes: 0
Views: 3063
Reputation: 29669
The reason you are getting that error message is because the *
operator is telling Ruby to pass all the items of arr
to str.include?
. For those arr
items, that is equivalent to writing str.include?("aa", "bb", "cc")
.
As said in other answers, checking a condition is verified for any of the elements contained in an array, like in your case (where you don't want to check if all the elements of an array are substrings of a given string), is done using arr.any? { |item| str.include?(item) }
.
Upvotes: 0
Reputation: 1380
Given:
arr = ["a", "b", "x"]
str = "DoDox"
EDIT: As the other comments have pointed out, this is actually the fastest way, as it breaks the evaluation when a single true statement is found:
arr.any?{|substr| str.include?(substr)}
The foldl way: I have used this example to illustrate the power of folding expresions. This solution might be somewhat elegant as an illustrative example for foldings, but it is not sufficiently performant.
arr.map{|substr| str.include?(substr)}.inject{|x,y| x || y}
The map
-function maps all possible substrings the original string str
can have. inject
iterates over the returning array and compares its constituents, using a logical or. If any substring in the array 'arr' is encountered, the result will yield true in the result of map. With the or-relation we return a true value, if any value of the result of map was true. This is slower than any?
, because every single value in the array gets evaluated even if a true
is encountered (wich would always yield a true
at the end of inject
).
["a", "b", "x"] -------> [false, false, true] ----------> true
map() inject()
Upvotes: -1
Reputation: 80065
Construct a Regular Expression (without pipes and slashes and dots and other magic stuff):
arr = ["aa", "bb", "cc"]
str = "mystringcc"
reg = Regexp.union(arr) # That's all!
p str.match?(reg) #=> true
Upvotes: 4
Reputation: 52357
You want to use Enumerable#any?
:
arr.any? { |substring| str.include?(substring) }
The solution is very efficient, because this method ensures short-circuit evaluation, meaning, that if you have array of 100000000 substrings and you want to check whether your string contains any of these substrings, this method will stop right when its block returns true
, meaning, that if the matching substring is first in the array, it will never check other 99999999 elements.
Upvotes: 10