数组合并(联合)
我有两个数组我需要合并,并使用联合(|)运算符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算子似乎永远占用
下面是一个基准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