如何判断我的字符串是否包含数组中的子字符串?
我以为include?
是关键,但显然不是......
arr = ["aa", "bb", "cc"]
str = "mystringcc"
str.include?(*arr)
ArgumentError: wrong number of arguments (given 3, expected 1)
在上面的示例中,我希望结果是true
因为字符串 has "cc"
,它是数组的一个元素。
你想使用Enumerable#any?
:
arr.any? { |substring| str.include?(substring) }
该解决方案非常有效,因为此方法可确保短路评估,这意味着,如果您有 100000000 个子字符串的数组,并且您想检查您的字符串是否包含这些子字符串中的任何一个,则此方法将在其块返回时立即停止true
,这意味着,如果匹配的子字符串在数组中是第一个,它将永远不会检查其他 99999999 个元素。
构造一个正则表达式(没有管道、斜线和点以及其他神奇的东西):
arr = ["aa", "bb", "cc"]
str = "mystringcc"
reg = Regexp.union(arr) # That's all!
p str.match?(reg) #=> true
您收到该错误消息的原因是*
操作员告诉 Ruby 传递 to 的所有arr
项目str.include?
。对于那些arr
项目,这相当于写作str.include?("aa", "bb", "cc")
。
正如在其他答案中所说,检查条件是否已针对数组中包含的任何元素进行验证,例如在您的情况下(您不想检查数组的所有元素是否都是给定字符串的子字符串),是使用arr.any? { |item| str.include?(item) }
.
鉴于:
arr = ["a", "b", "x"]
str = "DoDox"
编辑:正如其他评论指出的那样,这实际上是最快的方法,因为当找到一个真实的陈述时它会破坏评估:
arr.any?{|substr| str.include?(substr)}
foldl方式:我用这个例子来说明折叠表达式的威力。作为折叠的说明性示例,此解决方案可能有些优雅,但性能不够。
arr.map{|substr| str.include?(substr)}.inject{|x,y| x || y}
map
-function 映射原始字符串str
可以具有的所有可能的子字符串。inject
迭代返回的数组并使用逻辑或比较其组成部分。如果遇到数组 'arr' 中的任何子字符串,则结果将在 map 的结果中为 true。使用 or 关系,如果 map 的结果的任何值为真,我们将返回一个真值。这比 慢any?
,因为即使遇到 a ,数组中的每个值都会被评估(在 结束时true
总是会产生 a )。true
inject
["a", "b", "x"] -------> [false, false, true] ----------> true
map() inject()