Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting matching elements in an array

Tags:

arrays

ruby

Given two arrays of equal size, how can I find the number of matching elements disregarding the position?
For example:

  1. [0,0,5] and [0,5,5] would return a match of 2 since there is one 0 and one 5 in common;
  2. [1,0,0,3] and [0,0,1,4] would return a match of 3 since there are two matches of 0 and one match of 1;
  3. [1,2,2,3] and [1,2,3,4] would return a match of 3.

I tried a number of ideas, but they all tend to get rather gnarly and convoluted. I'm guessing there is some nice Ruby idiom, or perhaps a regex that would be an elegant answer to this solution.

like image 370
Joe Balsamo Avatar asked Jun 14 '15 16:06

Joe Balsamo


People also ask

How to count the number of elementwise matches between two NumPy arrays?

Let’s say we have two integer NumPy arrays and want to count the number of elementwise matches. To create a third (boolean) array that contains True for a match, and False otherwise, we can use the equality operator. Like to comment?

How do I quickly count objects in an array?

Knowing how to quickly iterate through an array and count objects is deceptively simple. The length () method will tell you the total number of values in the array, but what if you only want to count those values based on certain conditions? And you only want to count the number of objects with status set to '0'.

How to count occurrences of an array in Python?

Python program to count occurrences of in array using for loop # function to count def countOccurrences(arr, n, x): res = 0 for i in range(n): if x == arr[i]: res += 1 return res # array list arr = [1, 2, 2, 2, 2, 3, 4, 7 ,8 ,8] n = len(arr) x = 2 print (countOccurrences(arr, n, x))

How to get total count of match in a list in Python?

This problem can potentially be solved using the index function of python to get the wanted indices and list comprehension can be used to extend this to the whole string. The len () is used to return total count of match.


4 Answers

You can accomplish it with count:

a.count{|e| index = b.index(e) and b.delete_at index }

Demonstration

or with inject:

a.inject(0){|count, e| count + ((index = b.index(e) and b.delete_at index) ? 1 : 0)}

Demonstration

or with select and length (or it's aliassize):

a.select{|e| (index = b.index(e) and b.delete_at index)}.size

Demonstration

Results:

  1. a, b = [0,0,5], [0,5,5] output: => 2;
  2. a, b = [1,2,2,3], [1,2,3,4] output: => 3;
  3. a, b = [1,0,0,3], [0,0,1,4] output => 3.
like image 94
potashin Avatar answered Oct 08 '22 22:10

potashin


(arr1 & arr2).map { |i| [arr1.count(i), arr2.count(i)].min }.inject(0, &:+)

Here (arr1 & arr2) return list of uniq values that both arrays contain, arr.count(i) counts the number of items i in the array.

like image 45
Andrew Kozin Avatar answered Oct 08 '22 22:10

Andrew Kozin


Another use for the mighty (and much needed) Array#difference, which I defined in my answer here. This method is similar to Array#-. The difference between the two methods is illustrated in the following example:

a = [1,2,3,4,3,2,4,2]
b = [2,3,4,4,4]
a - b          #=> [1]
a.difference b #=>  [1, 3, 2, 2] 

For the present application:

def number_matches(a,b)
  left_in_b = b
  a.reduce(0) do |t,e|
    if left_in_b.include?(e)
      left_in_b = left_in_b.difference [e]
      t+1
    else
      t
    end
  end
end

number_matches [0,0,5],   [0,5,5]   #=> 2
number_matches [1,0,0,3], [0,0,1,4] #=> 3
number_matches [1,0,0,3], [0,0,1,4] #=> 3
like image 2
Cary Swoveland Avatar answered Oct 08 '22 23:10

Cary Swoveland


Using the multiset gem:

(Multiset.new(a) & Multiset.new(b)).size

Multiset is like Set, but allows duplicate values. & is the "set intersection" operator (return all things that are in both sets).

like image 1
Wayne Conrad Avatar answered Oct 08 '22 23:10

Wayne Conrad