简体   繁体   中英

How can I tell if my string contains a substring from an array?

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.

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.

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

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) } arr.any? { |item| str.include?(item) } arr.any? { |item| str.include?(item) } .

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM