有效地比较两个非常大的排序数组

时间:2014-09-10 14:57:01

标签: ruby arrays jruby

我需要找到一种有效的方法来找出两个大型排序数组之间的不同之处。换句话说,我需要根据与其他的比较找出从其中一个添加/删除的内容。排序是可选的,所以如果你认为我们可以实现没有排序的东西,那对我来说没问题。

这两个数组每个元素的长度都是一百万个,所以一次比较它们是不可行的。

这方面的背景很简单。我试图从远程遗留SQL(OpenEdge)表获取所有新行,这些表没有任何方法可以告诉什么是新的。我知道这可能听起来很奇怪,但这是我正在使用的现实。所以没有数据触发器,没有时间戳,没有。这已在另一个StackOverflow线程中解决,因此我不想找到将此功能添加到远程表的方法。

我在Postgresql本地数据库中有这个表的副本,以帮助进行比较。我正在通过网络进行比较,并使用jRuby和JDBC驱动程序来检查远程数据。到目前为止,我尝试将两个表加载到Ruby数组中并执行标准array - array,但这会占用太多内存(表每行长达一百万行)。

我还有其他选择吗?我不知道的任何算法?

1 个答案:

答案 0 :(得分:1)

如果两个数组都已经排序,那么您可以同时浏览两个数组并使用每个数组的索引比较元素。如果索引i和j处的元素等于,则前进两个索引。如果元素不同,那么只需前进索引,其中数组中的元素小于另一个数组中的元素。

这是此方法的代码。请注意,它假设两个数组都已排序,并且可以通过==<>对元素进行比较:

def compare_sorted_arrays a1, a2
  i, j = 0, 0
  output = []
  while i < a1.length and j < a2.length do
    if a1[i] == a2[j]
      i += 1
      j += 1
    elsif a1[i] < a2[j]
      output << a1[i]
      i += 1
    else
      output << a2[j]
      j += 1
    end
  end
  i.upto(a1.length-1) do |x|
    output << a1[x]
  end
  j.upto(a2.length-1) do |x|
    output << a2[x]
  end
  output
end

一个简单的测试

puts (compare_sorted_arrays([1, 2, 3, 4,], [1, 3, 5, 7])).join(', ')
puts (compare_sorted_arrays([1, 3, 5, 7], [1, 2, 3, 4,])).join(', ')

输出:

2, 4, 5, 7
2, 4, 5, 7

另一个选项可能是直接在SQL中执行symmetric difference,如下所示:Does the SQL spec provide for a better way to do a exclusive ORing of two sets?

SELECT COALESCE(A.id, B.id) AS id
FROM InitialTable A
FULL OUTER JOIN TableToCompareWith B
ON A.id = B.id
WHERE A.id IS NULL OR B.id IS NULL