61

I've got a long string-variable and want to find out whether it contains one of two substrings.

e.g.

haystack = 'this one is pretty long'
needle1 = 'whatever'
needle2 = 'pretty'

Now I'd need a disjunction like this which doesn't work in Ruby though:

if haystack.include? needle1 || haystack.include? needle2
    puts "needle found within haystack"
end

8 Answers 8

105
[needle1, needle2].any? { |needle| haystack.include? needle }
2
  • 2
    also works with .all? if you wanted AND logic instead of OR logic. Thanks, seph!
    – emery
    Commented Oct 30, 2015 at 2:52
  • 3
    this is the better answer if you need to be flexible with the amount of needles. needles = [obj1, obj2, ..., objN]; needles.any? { |needle| haystack.include? needle }
    – daybreaker
    Commented Jun 27, 2016 at 21:57
68

Try parens in the expression:

 haystack.include?(needle1) || haystack.include?(needle2)
1
  • Can't believe that was it. Thank you. Commented Aug 11, 2017 at 13:31
24

You can do a regex match:

haystack.match? /needle1|needle2/

Or if your needles are in an array:

haystack.match? Regexp.union(needles)

(For Ruby < 2.4, use .match without question mark.)

6
  • Your code has a typo, it should be match no question mark.
    – RobinSH
    Commented Mar 22, 2017 at 21:23
  • 2
    @SephCordovano How am I using it wrong and how can I correct it? To me it looks exactly the same as the match? method documentation example linked above.
    – Emil Laine
    Commented Apr 7, 2017 at 15:03
  • @SephCordovano your comment is confusing. You should either expand it or delete it.
    – red-o-alf
    Commented Oct 23, 2017 at 6:23
  • @jj_What's confusing about it? If you want to search for an array of substrings you use a union. Commented Oct 23, 2017 at 6:38
  • 2
    Please check your Ruby version before commenting. 2.4.0 has match? whereas previous Ruby versions did not have this method. Added a caveat to the answer to help address some of the comments mentioned here.
    – Sgnl
    Commented Feb 8, 2018 at 22:19
10
(haystack.split & [needle1, needle2]).any?

To use comma as separator: split(',')

9

For an array of substrings to search for I'd recommend

needles = ["whatever", "pretty"]

if haystack.match?(Regexp.union(needles))
  ...
end
6

To check if contains at least one of two substrings:

haystack[/whatever|pretty/]

Returns first result found

0

I was trying to find simple way to search multiple substrings in an array and end up with below which answers the question as well. I've added the answer as I know many geeks consider other answers and not the accepted one only.

haystack.select { |str| str.include?(needle1) || str.include?(needle2) }

and if searching partially:

haystack.select { |str| str.include?('wat') || str.include?('pre') }
0

Use or instead of ||

if haystack.include? needle1 or haystack.include? needle2

or has lower presedence than || , or is "less sticky" if you will :-)

1

Not the answer you're looking for? Browse other questions tagged or ask your own question.