Home > Mobile >  Find exact value overlap between two arrays [duplicate]
Find exact value overlap between two arrays [duplicate]

Time:09-16

I have two arrays

a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]

I want to return the values that appear in both arrays AND the exact amount that they appear

# => [1, 1, 3, 3]

I can't use a1 & a2 because that will return unique values ([1, 3])

What's the best way to achieve this?

CodePudding user response:

It looks like what you have there are not really arrays, they are multisets or bags.

There is a general rule in programming: if you choose your data representation right, your algorithms become simpler.

So, if you use multisets instead of arrays, your problem will become trivial, since what you are looking for is literally just the intersection of two multisets.

Unfortunately, there is no multiset implementation in the core or standard libraries, but there are a couple of multiset gems available on the web. For example, there is the multimap gem, which also includes a multiset. Unfortunately, it needs a little bit of love and care, since it uses a C extension that only works until YARV 2.2. There is also the multiset gem.

require 'multiset'

m1 = Multiset.new(a1)
#=> #<Multiset:#3 1, #1 2, #3 3>

m2 = Multiset.new(a2)
#=> #<Multiset:#2 1, #2 3, #2 5>

m = m1 & m2
#=> #<Multiset:#2 1, #2 3>

Personally, I am not too big a fan of the inspect output, but we can see what's going on and that the result is correct: m contains 2 × 1 and 2 × 3.

If you really need the result as an Array, you can use Multiset#to_a:

m.to_a
#=> [1, 1, 3, 3]

CodePudding user response:

At first I do get the intersection between a1 and a2 with (a1 & a2). After that I iterate over the intersection and check which array has a lower count of each element. The element gets than added to the result array as many times as it occurs in the array with the lower count using result.fill

a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]

result = []
(a1 & a2).each do |e|
    a1.count(e) < a2.count(e) ? result.fill(e, result.size, a1.count(e)) : result.fill(e, result.size, a2.count(e))
end

pp result

  •  Tags:  
  • ruby
  • Related