Reputation: 7748
I have an array of strings a
, and I want to check if another long string b
contains any of the strings in the array
a = ['key','words','to', 'check']
b = "this is a long string"
What different options do I have to accomplish this?
For example this seems to work
not a.select { |x| b.include? x }.empty?
But it returns a negative response, thats why I had not
, any other ideas or differents ways?
Upvotes: 5
Views: 8243
Reputation: 84453
There are a number of ways to do what you want, but I like to program for clarity of purpose even when it's a little more verbose. The way that groks best to me is to scan the string for each member of the array, and then see if the flattened result has any members. For example:
a = ['key','words','to', 'check']
b = "this is a long string"
a.map { |word| b.scan /#{word}/ }.flatten.any?
# => false
a << 'string'
a.map { |word| b.scan /#{word}/ }.flatten.any?
# => true
The reason this works is that scan returns an array of matches, such as:
=> [[], [], [], [], ["string"]]
Array#flatten ensures that the empty nested arrays are removed, so that Enumerable#any? behaves the way you'd expect. To see why you need #flatten, consider the following:
[[], [], [], []].any?
# => true
[[], [], [], []].flatten.any?
# => false
Upvotes: 1
Reputation: 118299
There you go using #any?.
a = ['key','words','to', 'check']
b = "this is a long string"
a.any? { |s| b.include? s }
Or something like using ::union
. But as per the need, you might need to change the regex, to some extent it can be done. If not, then I will go with above one.
a = ['key','words','to', 'check']
Regexp.union a
# => /key|words|to|check/
b = "this is a long string"
Regexp.union(a) === b # => false
Upvotes: 16
Reputation: 7181
You could also use the array intersection (#&) method:
a = ['key','words','to', 'check']
b = "this is a long string"
shared = a & b.gsub(/[.!?,'"]/, "").split(/\s/)
Which would return an array containing all the shared characters.
Upvotes: 0