Ruby - 数组交集(有重复) [英] Ruby - array intersection (with duplicates)

查看:16
本文介绍了Ruby - 数组交集(有重复)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有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)的第一个元素被传递给block并赋值给block变量:

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]

so 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_mapEnumerable#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] 

如果数组 array1array2 很大并且需要考虑效率,我们可以做一点 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆