59

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
Hedge
  • 16,142
  • 42
  • 141
  • 246

8 Answers8

104
[needle1, needle2].any? { |needle| haystack.include? needle }
seph
  • 6,066
  • 3
  • 21
  • 19
  • 2
    also works with .all? if you wanted AND logic instead of OR logic. Thanks, seph! – emery Oct 30 '15 at 02: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 Jun 27 '16 at 21:57
66

Try parens in the expression:

 haystack.include?(needle1) || haystack.include?(needle2)
danh
  • 62,181
  • 10
  • 95
  • 136
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.)

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • Your code has a typo, it should be `match` no question mark. – RobinSH Mar 22 '17 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 Apr 07 '17 at 15:03
  • @SephCordovano your comment is confusing. You should either expand it or delete it. – Redoman Oct 23 '17 at 06:23
  • @jj_What's confusing about it? If you want to search for an array of substrings you use a union. – Seph Cordovano Oct 23 '17 at 06: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 Feb 08 '18 at 22:19
  • This is a fantastic answer. Clean and scalable. – Joshua Pinter Feb 15 '19 at 03:52
10
(haystack.split & [needle1, needle2]).any?

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

rgtk
  • 3,240
  • 1
  • 30
  • 36
9

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

needles = ["whatever", "pretty"]

if haystack.match?(Regexp.union(needles))
  ...
end
Darme
  • 6,984
  • 5
  • 37
  • 52
Seph Cordovano
  • 1,824
  • 1
  • 16
  • 19
5

To check if contains at least one of two substrings:

haystack[/whatever|pretty/]

Returns first result found

Kapitula Alexey
  • 380
  • 4
  • 15
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') }
Shiko
  • 2,448
  • 1
  • 24
  • 31
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 :-)

folium
  • 353
  • 1
  • 15
  • Using "or" instead of "||" is generally considered as a bad idea. No matter it will actually work in that specific case. More info: https://github.com/rubocop/ruby-style-guide#andor- and https://graceful.dev/courses/the-freebies/modules/ruby-language/topic/episode-125-and-or/ – Not Entered Apr 06 '23 at 00:49