I just wanted to concatenate multiple arrays in Ruby and couldn\'t find a satisfying way to do so.
Example input:
foo = [1, 2, 3]
ba
Did some benchmarks and simple + is the most efficient. So i would suggest to neglect the intermediate creation of an array.
You could add a new method concat_all to Array like this, but you would have to take into account mixed and multi-dimensional arrays also.
class Array
def concat_all
self.reduce([], :+)
end
end
[a, b, c].concat_all # a huge array
[a, b, c].concat_all.length #300000
Here my benchmarks
require 'Benchmark'
N = 1000
class Array
def concat_all
self.reduce([], :+)
end
def concat_all2
# just a quick test with fixed numbers for the fill method Stephan proposes but in Ruby itself
d = Array.new(300_000)
d[0..99999] = self[0]
d[100_000..199999] = self[1]
d[200_000..299999] = self[2]
d
end
def concat_all3
self.flatten
end
end
# small arrays
a = (1..10).to_a
b = (11..20).to_a
c = (21..30).to_a
Benchmark.bm do |r|
r.report('plus ') { N.times { a + b + c }}
r.report('concat ') { N.times { [].concat(a).concat(b).concat(c) }}
r.report('push ') { N.times { [].push(*a).push(*b).push(*c) }}
r.report('<< ') { N.times { ([] << a << b << c).flatten}}
r.report('splash ') { N.times {[*a, *b, *c]} }
r.report('concat_all ') { N.times { [a, b, c].concat_all }}
r.report('concat_all3') { N.times { [a, b, c].concat_all3 }}
r.report('flat_map ') { N.times {[a, b, c].flat_map(&:itself)} }
end
#large arrays
a = (1..100_000).to_a
b = (100_001..200_000).to_a
c = (200_001..300_000).to_a
Benchmark.bm do |r|
r.report('plus ') { N.times { a + b + c }}
r.report('concat ') { N.times { [].concat(a).concat(b).concat(c) }}
r.report('push ') { N.times { [].push(*a).push(*b).push(*c) }}
r.report('<< ') { N.times { ([] << a << b << c).flatten}}
r.report('splash ') { N.times {[*a, *b, *c]} }
r.report('concat_all ') { N.times { [a, b, c].concat_all }}
r.report('concat_all2') { N.times { [a, b, c].concat_all2 }}
r.report('concat_all3') { N.times { [a, b, c].concat_all3 }}
r.report('flat_map ') { N.times {[a, b, c].flat_map(&:itself)} }
end
And here the results
# results for small arrays
user system total real
plus 0.000000 0.000000 0.000000 ( 0.000416)
concat 0.000000 0.000000 0.000000 ( 0.000592)
push 0.000000 0.000000 0.000000 ( 0.000441)
<< 0.000000 0.000000 0.000000 ( 0.003387)
splash 0.000000 0.000000 0.000000 ( 0.000789)
concat_all 0.000000 0.000000 0.000000 ( 0.001480)
concat_all3 0.016000 0.000000 0.016000 ( 0.003496)
flat_map 0.000000 0.000000 0.000000 ( 0.001036)
# results for big arrays
user system total real
plus 0.686000 0.671000 1.357000 ( 1.351171)
concat 0.890000 0.733000 1.623000 ( 1.630155)
push 1.466000 0.624000 2.090000 ( 2.092684)
<< 23.837000 1.045000 24.882000 ( 24.885238)
splash 1.029000 1.264000 2.293000 ( 2.332560)
concat_all 0.687000 0.967000 1.654000 ( 1.709321)
concat_all2 0.936000 0.780000 1.716000 ( 1.730428)
concat_all3 24.242000 0.998000 25.240000 ( 25.278264)
flat_map 0.780000 0.765000 1.545000 ( 1.551654)