问题
I am trying to see if an array contains each element of another array. Plus I want to account for the duplicates. For example:
array = [1, 2, 3, 3, "abc", "de", "f"]
array contains [1, 2, 3, 3] but does not contain [2, 2, "abc"] - too many 2's
I have tried the below but obviously doesn't take into account the dupes.
other_arrays.each { |i| array.include? i }
回答1:
This method iterates once over both arrays. For each array, it creates a hash with the number of occurences of each element.
It then checks that for every unique element in subset
, there are at least as many elements in superset
.
class Array
def count_by
each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
end
def subset_of?(superset)
superset_counts = superset.count_by
count_by.all? { |k, count| superset_counts[k] >= count }
end
end
[1, 2, 3, 3, "abc", "de", "f"].count_by
#=> {1=>1, 2=>1, 3=>2, "abc"=>1, "de"=>1, "f"=>1}
[1, 2, 3, 3].count_by
#=> {1=>1, 2=>1, 3=>2}
[1, 2, 3, 3].subset_of? [1, 2, 3, 3, "abc", "de", "f"]
#=> true
[2, 2, "abc"].subset_of? [1, 2, 3, 3, "abc", "de", "f"]
#=> false
If you don't want to patch the Array
class, you could define :
count_by(array)
and subset_of?(array1, array2)
.
回答2:
You could first create a useful instance method for the class Array
:
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
Then all elements of an array a
are contained in array b
if the following method returns true
.
def subarray?(a,b)
a.difference(b).empty?
end
For example,
subarray? [1,2,3], [1,4,"cat",3,2]
#=> true
subarray? [1,2,3], [1,4,"cat",3,5]
#=> false
I've found Array#difference
has such wide application that I proposed that it be added to the Ruby core. Details about the method and its uses can be found at the link and also in my answer to this SO question.
来源:https://stackoverflow.com/questions/42008449/comparing-array-elements-including-duplicates