Philip7899
Philip7899

Reputation: 4677

Compare two ruby arrays and return similar items

I have two arrays:

array1 = ["hello friend", "goodbye enemy", "yolo", "jello"]
array2 = ["ello", "random"]

I need to write a method that returns an array of the elements in array1 that include in a string item any of the items in array2. So the method should return:

["hello friend", "jello"]

I've tried array1.reject{|i| array1.include? array2} but it just returns array1. What should I do?

Upvotes: 0

Views: 1343

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110675

array1 = ["hello friend", "goodbye enemy", "yolo", "jello", "Randomize"]
array2 = ["ello", "random"]

r = Regexp.new(Regexp.union(array2).source, 'i')
  #=> /ello|random/i  
array1.grep(r)
  #=> ["hello friend", "jello", "Randomize"] 

See Regexp::new, Regexp::union, Regexp#source and Enumerable#grep.

Upvotes: 2

Chris Heald
Chris Heald

Reputation: 62648

You're on the right track, but missing some fundamentals.

  1. #reject selects those elements which do not satisfy the block condition
  2. Your block condition is testing if an element of array1 matches the entire array2 array - since a string and array will never match, all elements of array1 fail the test, and are thus returned.

Unrolling it, you have these tests:

"hello friend" == ["ello", "random"] # => false
"goodbye enemy" == ["ello", "random"] # => false
# etc

Assuming you want all elements from array1 for which any element in array2 is a substring:

array1.select do |i|
  array2.any? {|j| i.include?(j) }
end

This means "select all elements from array1 for which any element in array2 is a substring of the array1 element".

Unrolled, this gives you the following tests:

"hello friend".include?("ello") # => true
"hello friend".include?("random") # => false
"goodbye enemy".include?("ello") # => false
"goodbye enemy".include?("random") # => false
# etc

#any? returns true if any element in the Enumerable matches the block condition, so unrolled:

["ello", "random"].any? {|i| "hello friend".include?(i) } # => true
["ello", "random"].any? {|i| "goodbye enemy".include?(i) } # => false

Since #select returns those elements for which the block condition is true, "hello friend" would be returned, while "goodbye enemy" would not.

Upvotes: 3

Related Questions