arrays - Ruby - 数组交集(有重复项)

标签 arrays ruby intersection

我有 数组(1 和 2)。我怎样才能从他们那里得到 array3

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).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 变量:

n = 2

并进行区 block 计算:

[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]

您是否记不住 Enumerable#flat_map不同于 Enumerable#map ?假设我使用了 map 而不是 flat_map。然后

a.map { |n| [n]*[array1.count(n), array2.count(n)].min }
  #=> [[2, 2, 2], [3], [4], [8]]

flat_map 只是在每个数组前面放置一个 splat:

[*[2, 2, 2], *[3], *[4], *[8]]
  #=> [2, 2, 2, 3, 4, 8] 

如果数组 array1array2 很大并且效率是一个问题,我们可以做一些 O(N) 的预处理:

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]

关于arrays - Ruby - 数组交集(有重复项),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38020334/

相关文章:

php - 从 PHP 数组中删除所有非字符串元素

ruby-on-rails - 如何使Ruby方法结束/停止另一个请求? (rails API)

ruby-on-rails - 我的脚本会发送很多请求吗?

ruby-on-rails - 基于参数的动态 ActiveRecord 查找器方法链接

matlab - 如何在 MATLAB 中找到两个椭圆的交点

arrays - 在属性写入中引用一个公共(public) setter

arrays - 为什么在我的 if 语句中添加不等于空格会导致错误?

python - 在 tensorflow 中找到两个边界框的交集?

c++ - 确定从一个点出发的无限直线(一个方向)是否与二维中的线段相交

c++ - std::vector 和 std::array 初始化列表之间的区别