I need to tell if an array contains all of the elements of another array with duplicates.
[1,2,3].contains_all? [1,2] #=> true
[1,2,3].contains_all
Here's a naive and straightforward implementation (not the most efficient one, likely). Just count the elements and compare both elements and their occurrence counts.
class Array
def contains_all? ary
# group the arrays, so that
# [2, 1, 1, 3] becomes {1 => 2, 2 => 1, 3 => 1}
my_groups = group_and_count self
their_groups = group_and_count ary
their_groups.each do |el, cnt|
if !my_groups[el] || my_groups[el] < cnt
return false
end
end
true
end
private
def group_and_count ary
ary.reduce({}) do |memo, el|
memo[el] ||= 0
memo[el] += 1
memo
end
end
end
[1, 2, 3].contains_all? [1, 2] # => true
[1, 2, 3].contains_all? [1, 2, 2] # => false
[2, 1, 2, 3].contains_all? [1, 2, 2] # => true
[1, 2, 3].contains_all? [] # => true
[].contains_all? [1, 2] # => false
It seems you need a multiset. Check out this gem, I think it does what you need.
You can use is and do something like (if the intersection is equal to the second multiset then the first one includes all of its elements):
@ms1 & @ms2 == @ms2