Ruby-数组交集(重复项) [英] Ruby - array intersection (with duplicates)
问题描述
我有array(1 and 2)
.我如何从他们那里得到array3
?
I have array(1 and 2)
. How can I get array3
from them?
array1 = [2,2,2,2,3,3,4,5,6,7,8,9]
array2 = [2,2,2,3,4,4,4,4,8,8,0,0,0]
array3 = [2,2,2,3,4,8]
array1 & array2
返回[2,3,4,8]
,但我需要保留重复项.
array1 & array2
returns [2,3,4,8]
, but I need to hold onto the duplicates.
推荐答案
(array1 & array2).flat_map { |n| [n]*[array1.count(n), array2.count(n)].min }
#=> [2,2,2,3,4,8]
步骤:
a = array1 & array2
#=> [2, 3, 4, 8]
a
(2
)的第一个元素传递到块并分配给块变量:
The first element of a
(2
) is passed to the block and assigned to the block variable:
n = 2
并执行块计算:
[2]*[array1.count(2), array2.count(2)].min
#=> [2]*[4,3].min
#=> [2]*3
#=> [2,2,2]
因此2
映射到[2,2,2]
.对于a
的其余三个元素,计算结果相似.当我使用flat_map
时,这将返回[2,2,2,3,4,8]
.
so 2
is mapped to [2,2,2]
. The calculations are similar for the remaining three elements of a
. As I am using flat_map
, this returns [2,2,2,3,4,8]
.
您是否难以记住 Enumerable#flat_map 与 Enumerable#map ?假设我使用的是map
而不是flat_map
.然后
Do you have trouble remembering how Enumerable#flat_map differs from Enumerable#map? Suppose I had used map
rather than flat_map
. Then
a.map { |n| [n]*[array1.count(n), array2.count(n)].min }
#=> [[2, 2, 2], [3], [4], [8]]
flat_map
所做的仅是将splat放在每个数组的前面:
flat_map
does nothing more that put a splat in front of each of those arrays:
[*[2, 2, 2], *[3], *[4], *[8]]
#=> [2, 2, 2, 3, 4, 8]
如果数组array1
和array2
很大并且效率是一个问题,我们可以做一些O(N)预处理:
If the arrays array1
and array2
are large and efficiency is a concern, we could do a bit of O(N) pre-processing:
def cnt(arr)
arr.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
end
cnt1 = cnt(array1)
#=> {2=>4, 3=>2, 4=>1, 5=>1, 6=>1, 7=>1, 8=>1, 9=>1}
cnt2 = cnt(array2)
#=> {2=>3, 3=>1, 4=>4, 8=>2, 0=>3}
(array1 & array2).flat_map { |n| [n]*[cnt1[n], cnt2[n]].min }
#=> [2,2,2,3,4,8]
这篇关于Ruby-数组交集(重复项)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!