保持Ruby中重复元素的数组之间的差异

我是Ruby的新手,并且希望能够在两个数组之间找到差异.

我知道通常的方法:

a = [...]
b = [...]
difference = (a-b)+(b-a)

但问题在于这是计算集合差异,因为在ruby中,语句(a-b)定义了a相对于b的集合恭维.

这意味着[1,2,2,3,4,5,5,5,5] – [5] = [1,2,2,3,4],因为它在第一次中取出了所有出现的5设置,而不仅仅是一个,表现得像数据上的过滤器.

我希望它只删除一次差异,例如,[1,2,2,3,4,5,5,5,5]和[5]的差异应为[1,2,2,3] ,4,5,5,5],只删除一个5.

我可以迭代地做到这一点:

a = [...]
b = [...]

complimentAbyB = a.dup
complimentBbyA = b.dup

b.each do |bValue|
  complimentAbyB.delete_at(complimentAbyB.index(bValue) || complimentAbyB.length)
end
a.each do |aValue|
  complimentBbyA.delete_at(complimentBbyA.index(aValue) || complimentBbyA.length)
end

difference = complimentAbyB + complimentBbyA

但这看起来非常冗长和低效.我不得不想象有一个更优雅的解决方案.所以我的问题基本上是,找到两个数组的差异的最优雅的方法是什么,如果一个数组出现单个元素然后另一个数组,它们将不会被删除?

最佳答案
我最近提出将这样的方法Ruby#difference添加到Ruby的核心.对于你的例子,它将写成:

a = [1,2,2,3,4,5,5,5,5]
b = [5]

a.difference b
  #=> [1,2,2,3,4,5,5,5]

我经常给出的例子是:

a = [3,1,2,3,4,3,2,2,4]
b = [2,3,4,4,3,4]

a.difference b
  #=> [1, 3, 2, 2] 

我在答案here中首先提出了这个方法.在那里你会找到一个解释和其他SO问题的链接,我建议使用这个方法.

如链接所示,该方法可以写成如下:

class Array
  def difference(other)
    h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end

转载注明原文:保持Ruby中重复元素的数组之间的差异 - 代码日志