The Spaghetti Refactory Established 2015

Check if array contains any element of another array

I wanted to check if there were common elements in two separate arrays. Seems simple enough, but I was trying to find a way to do this without looping over both arrays in some kind each jungle:

wizard_of_oz_characters = ['tin man', 'scarecrow', 'lion']
batman_villains = ['scarecrow', 'joker', 'bane']
wizard_of_oz_characters.each do |character|
batman_villains.each do |villain|
return false if character == villain
end
end

I was able to pare it down to something simpler:

wizard_of_oz_characters.any? {|character| batman_villains.include?(character) }

…but at it’s core, it’s still looping through and checking each record in sequence. Not what I was after.

Then I found a StackOverflow answer which had exactly what I wanted:

(wizard_of_oz_characters & batman_villains).empty?

This returns the intersection of the two arrays (['scarecrow']), then asks if it is empty. Perfect! And the syntax is kinda fun too.

But what is it actually doing? One of the comments on the SO answer said this is faster because it’s linear rather than quadratic, and although it has been a few years since high school Geometry, I still know quadratic is much more intensive than linear. However, I wanted to find out more.

Turns out, the & operator is treating the Arrays like Sets, an entirely different data type in Ruby. From the Ruby docs themselves, a Set is a “hybrid of Array’s intuitive inter-operation facilities and Hash’s fast lookup.”

So you get the syntax of an Array with the speed of a Hash. And you get this fun and terse syntax. I’m on board with that.

Tags