2

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
  • Similarly used the .all? method other_arrays.all? {|x| array.include? x } Commented Feb 2, 2017 at 17:24

2 Answers 2

3

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).

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.