计算数组中的匹配元素

时间:2022-05-10 22:23:07

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. [0,0,5]和[0,5,5]将返回2的匹配,因为共有一个0和一个5;

  3. [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;
  4. [1,0,0,3]和[0,0,1,4]将返回3的匹配,因为有两个匹配0和一个匹配1;

  5. [1,2,2,3] and [1,2,3,4] would return a match of 3.
  6. [1,2,2,3]和[1,2,3,4]将返回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.

我尝试了很多想法,但它们都倾向于变得相当粗糙和复杂。我猜测有一些很好的Ruby习惯用法,或者也许是一个正则表达式,可以很好地回答这个解决方案。

5 个解决方案

#1


4  

You can accomplish it with count:

你可以用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 = [0,0,5],[0,5,5]输出:=> 2;

  3. a, b = [1,2,2,3], [1,2,3,4] output: => 3;
  4. a,b = [1,2,2,3],[1,2,3,4]输出:=> 3;

  5. a, b = [1,0,0,3], [0,0,1,4] output => 3.
  6. a,b = [1,0,0,3],[0,0,1,4]输出=> 3。

#2


3  

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

这里(arr1和arr2)返回两个数组包含的uniq值列表,arr.count(i)计算数组中项目的数量。

#3


2  

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:

强大(和急需)阵列#差异的另一个用途,我在这里的答案中定义了它。此方法类似于Array# - 。以下示例说明了这两种方法之间的区别:

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

#4


1  

Using the multiset gem:

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

Multiset与Set类似,但允许重复值。 &是“set intersection”运算符(返回两个集合中的所有内容)。

#5


0  

I don't think this is an ideal answer, because it's a bit complex, but...

我不认为这是一个理想的答案,因为它有点复杂,但......

def count(arr)
  arr.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
end

def matches(a1, a2)
  m = 0
  a1_counts = count(a1)
  a2_counts = count(a2)
  a1_counts.each do |e, c|
    m += [a1_counts, a2_counts].min
  end
  m
end

Basically, first write a method that creates a hash from an array of the number of times each element appears. Then, use those to sum up the smallest number of times each element appears in both arrays.

基本上,首先编写一个方法,从每个元素出现的次数的数组创建一个哈希。然后,使用它们来总结每个元素在两个数组中出现的最小次数。

#1


4  

You can accomplish it with count:

你可以用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 = [0,0,5],[0,5,5]输出:=> 2;

  3. a, b = [1,2,2,3], [1,2,3,4] output: => 3;
  4. a,b = [1,2,2,3],[1,2,3,4]输出:=> 3;

  5. a, b = [1,0,0,3], [0,0,1,4] output => 3.
  6. a,b = [1,0,0,3],[0,0,1,4]输出=> 3。

#2


3  

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

这里(arr1和arr2)返回两个数组包含的uniq值列表,arr.count(i)计算数组中项目的数量。

#3


2  

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:

强大(和急需)阵列#差异的另一个用途,我在这里的答案中定义了它。此方法类似于Array# - 。以下示例说明了这两种方法之间的区别:

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

#4


1  

Using the multiset gem:

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

Multiset与Set类似,但允许重复值。 &是“set intersection”运算符(返回两个集合中的所有内容)。

#5


0  

I don't think this is an ideal answer, because it's a bit complex, but...

我不认为这是一个理想的答案,因为它有点复杂,但......

def count(arr)
  arr.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
end

def matches(a1, a2)
  m = 0
  a1_counts = count(a1)
  a2_counts = count(a2)
  a1_counts.each do |e, c|
    m += [a1_counts, a2_counts].min
  end
  m
end

Basically, first write a method that creates a hash from an array of the number of times each element appears. Then, use those to sum up the smallest number of times each element appears in both arrays.

基本上,首先编写一个方法,从每个元素出现的次数的数组创建一个哈希。然后,使用它们来总结每个元素在两个数组中出现的最小次数。