Intersecting Arrays in Ruby
Just found a slightly satisfying approach to checking the contents of an array in ruby.
I like using Array#include?
to figure out whether or not my given array has a certain entry. Unfortunately, if you want to check if an array has a set of possible values, such as, does it contain :a
or :b
, you can’t just pass an array of those values. Let me show you what I mean:
food = [:milk, :bread, :butter]
food1 = [[:milk, :bread], :butter]
expected = [:milk, :bread]
food.include?(:milk) # => true
food.include?(expected) # => false
food1.include?(expected) # => true
In other words, include?
is very specific about the way it does the matching. But what if I want food.include?(expected)
to tell me if food
has any of expected
‘s values? Enter Array#&
. It doesn’t make include?
do anything different, but does give us a simple way to get this newer behavior:
food = [:milk, :bread, :butter]
expected = [:milk, :bread]
(food & expected).size > 0 # => true
Array#&
gets the intersection of two arrays (the values that are present in both) and returns a new array containing only those values. You could add this to any Array
instance by simply defining your own include_any?
method:
# myapp/lib/ext/array.rb
class Array
def include_any? values
(self & values).size > 0
end
def include_all? values
(self & values).size == values.size
end
end
[:milk, :bread, :butter].include_any?([:milk, :butter]) # => true
[:milk, :bread, :butter].include_all?([:milk, :butter]) # => false
[:milk, :bread, :butter].include_all?([:milk, :butter, :bread]) # => true
I cheated and gave you an include_all?
method also, which just ensures that all of the expected values are present.
I could’ve used Enumerable#any?
but then we’d have to use a block and still use Array#include?
. This way, we’re golden.
What cool things have you done with ruby today?