Given two arrays of equal size, how can I find the number of matching elements disregarding the position?
For example:
给定两个大小相等的数组,如何找到匹配元素的数量而忽略位置?例如:
-
[0,0,5]
and[0,5,5]
would return a match of2
since there is one0
and one5
in common; -
[1,0,0,3]
and[0,0,1,4]
would return a match of3
since there are two matches of0
and one match of1
; -
[1,2,2,3]
and[1,2,3,4]
would return a match of3
.
[0,0,5]和[0,5,5]将返回2的匹配,因为共有一个0和一个5;
[1,0,0,3]和[0,0,1,4]将返回3的匹配,因为有两个匹配0和一个匹配1;
[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 }
or with inject
:
或注入:
a.inject(0){|count, e| count + ((index = b.index(e) and b.delete_at index) ? 1 : 0)}
or with select
and length
(or it's alias – size
):
或选择和长度(或它的别名 - 大小):
a.select{|e| (index = b.index(e) and b.delete_at index)}.size
Results:
-
a, b = [0,0,5], [0,5,5]
output:=> 2
; -
a, b = [1,2,2,3], [1,2,3,4]
output:=> 3
; -
a, b = [1,0,0,3], [0,0,1,4]
output=> 3
.
a,b = [0,0,5],[0,5,5]输出:=> 2;
a,b = [1,2,2,3],[1,2,3,4]输出:=> 3;
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
#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 }
or with inject
:
或注入:
a.inject(0){|count, e| count + ((index = b.index(e) and b.delete_at index) ? 1 : 0)}
or with select
and length
(or it's alias – size
):
或选择和长度(或它的别名 - 大小):
a.select{|e| (index = b.index(e) and b.delete_at index)}.size
Results:
-
a, b = [0,0,5], [0,5,5]
output:=> 2
; -
a, b = [1,2,2,3], [1,2,3,4]
output:=> 3
; -
a, b = [1,0,0,3], [0,0,1,4]
output=> 3
.
a,b = [0,0,5],[0,5,5]输出:=> 2;
a,b = [1,2,2,3],[1,2,3,4]输出:=> 3;
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.
基本上,首先编写一个方法,从每个元素出现的次数的数组创建一个哈希。然后,使用它们来总结每个元素在两个数组中出现的最小次数。