数组合并(联合)

我有两个数组我需要合并,并使用联合(|)运算符PAINFULLY慢..有没有其他方法来完成数组合并?

另外,数组中填充了对象,而不是string。

数组中的对象的示例

#<Article id: 1, xml_document_id: 1, source: "<article><domain>events.waikato.ac</domain><excerpt...", created_at: "2010-02-11 01:32:46", updated_at: "2010-02-11 01:41:28" > 

哪里来源是一小段XML。

编辑

抱歉! 通过“合并”我的意思是我不需要插入重复。

 A => [1, 2, 3, 4, 5] B => [3, 4, 5, 6, 7] A.magic_merge(B) #=> [1, 2, 3, 4, 5, 6, 7] 

了解这些整数实际上是Article对象,并且Union算子似乎永远占用

4 Solutions collect form web for “数组合并(联合)”

下面是一个基准testing两个合并技巧的脚本:使用pipe道运算符( a1 | a2 )和使用concatenate-and-uniq( (a1 + a2).uniq )。 两个额外的基准分别给出了concatenate和uniq的时间。

 require 'benchmark' a1 = []; a2 = [] [a1, a2].each do |a| 1000000.times { a << rand(999999) } end puts "Merge with pipe:" puts Benchmark.measure { a1 | a2 } puts "Merge with concat and uniq:" puts Benchmark.measure { (a1 + a2).uniq } puts "Concat only:" puts Benchmark.measure { a1 + a2 } puts "Uniq only:" b = a1 + a2 puts Benchmark.measure { b.uniq } 

在我的机器上(Ubuntu Karmic,Ruby 1.8.7),我得到这样的输出:

 Merge with pipe: 1.000000 0.030000 1.030000 ( 1.020562) Merge with concat and uniq: 1.070000 0.000000 1.070000 ( 1.071448) Concat only: 0.010000 0.000000 0.010000 ( 0.005888) Uniq only: 0.980000 0.000000 0.980000 ( 0.981700) 

这说明这两种技术在速度上非常相似, uniq是操作的更大的组成部分。 这是直观的,O(n)(最好),而简单的级联是O(1)。

所以,如果你真的想加快速度,你需要看看<=>操作符是如何实现数组中的对象的。 我相信大部分时间都在比较对象,以确保最终arrays中任何一对之间的不平等。

你需要在数组内的特定顺序的项目? 如果没有,你可能想要检查使用Set s是否使它更快。

更新

添加到另一个回答者的代码:

 require "set" require "benchmark" a1 = []; a2 = [] [a1, a2].each do |a| 1000000.times { a << rand(999999) } end s1, s2 = Set.new, Set.new [s1, s2].each do |s| 1000000.times { s << rand(999999) } end puts "Merge with pipe:" puts Benchmark.measure { a1 | a2 } puts "Merge with concat and uniq:" puts Benchmark.measure { (a1 + a2).uniq } puts "Concat only:" puts Benchmark.measure { a1 + a2 } puts "Uniq only:" b = a1 + a2 puts Benchmark.measure { b.uniq } puts "Using sets" puts Benchmark.measure {s1 + s2} puts "Starting with arrays, but using sets" puts Benchmark.measure {s3, s4 = [a1, a2].map{|a| Set.new(a)} ; (s3 + s4)} 

(对于ruby1.8.7(2008-08-11 patchlevel 72)[universal-darwin10.0])

 Merge with pipe: 1.320000 0.040000 1.360000 ( 1.349563) Merge with concat and uniq: 1.480000 0.030000 1.510000 ( 1.512295) Concat only: 0.010000 0.000000 0.010000 ( 0.019812) Uniq only: 1.460000 0.020000 1.480000 ( 1.486857) Using sets 0.310000 0.010000 0.320000 ( 0.321982) Starting with arrays, but using sets 2.340000 0.050000 2.390000 ( 2.384066) 

根据您的情况(大量合并或不太多的合并),build议集合可能也可能不会更快。

根据我使用Ruby 1.8.7的初始基准,使用Array#concat方法可能会快很多:

 require 'benchmark' def reset_arrays! @array1 = [] @array2 = [] [@array1, @array2].each do |array| 10000.times { array << ActiveSupport::SecureRandom.hex } end end reset_arrays! && puts(Benchmark.measure { @array1 | @array2 }) # => 0.030000 0.000000 0.030000 ( 0.026677) reset_arrays! && puts(Benchmark.measure { @array1.concat(@array2) }) # => 0.000000 0.000000 0.000000 ( 0.000122) 

试试这个,看看这是否更快

 a = [1,2,3,3,2] b = [1,2,3,4,3,2,5,7] (a+b).uniq 
  • 运行wkhtmltopdf错误 - (加载共享库时出错)
  • Ruby块语法错误
  • 在导轨中删除模型(“导轨g模型标题”的反转)
  • Ruby / Rails - 更改时间的时区,而不更改值
  • Rails - validation协会的存在?
  • Ruby JSONparsing修改哈希键
  • Rails浏览器检测方法
  • Rails:Javascriptstring的国际化?
  • 如何在Rails中混入并从controller中调用link_to?
  • 获得水豚testing的下拉select值
  • 在ruby中告诉一个.each循环的结束