I benchmarked the various suggestions and added some of my own, and the
results may surprise some (they surprised me!)
Rehearsal --------------------------------------------------------------
:zip_flatten_technique 8.280000 0.000000 8.280000 ( 19.532383)
:enum_cons_technique 18.190000 0.020000 18.210000 ( 28.552418)
:copy_inject_technique 5.500000 0.000000 5.500000 ( 5.567597)
:fill_technique 5.250000 0.010000 5.260000 ( 5.373526)
:naive_technique 5.040000 0.000000 5.040000 ( 5.091017)
:flatten_compact_technique 7.900000 0.000000 7.900000 ( 7.938109)
![Eek! :eek: :eek:](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
riginal_technique 2.560000 0.000000 2.560000 ( 2.620933)
:zip_concat_technique 6.480000 0.000000 6.480000 ( 6.493874)
---------------------------------------------------- total: 59.230000sec
user system total real
:zip_flatten_technique 7.500000 0.000000 7.500000 ( 7.636382)
:enum_cons_technique 17.790000 0.680000 18.470000 ( 18.536960)
:copy_inject_technique 5.250000 0.000000 5.250000 ( 5.277144)
:fill_technique 5.070000 0.010000 5.080000 ( 5.165221)
:naive_technique 5.100000 0.010000 5.110000 ( 5.113858)
:flatten_compact_technique 7.330000 0.000000 7.330000 ( 7.350595)
![Eek! :eek: :eek:](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
riginal_technique 2.590000 0.000000 2.590000 ( 2.600783)
:zip_concat_technique 6.190000 0.000000 6.190000 ( 6.197641)
So the OP's technique, if not the prettiest, is actually by far the
fastest, and is correct when used with nested arrays. Some of the other
solutions (that use flatten) are incorrect when used with nested arrays.
Here's the code:
require 'benchmark'
require 'enumerator'
techniques = {
:enum_cons_technique => lambda {|arr|
arr.enum_cons(2).inject([]) {|a, i| a+i}},
:zip_flatten_technique => lambda {|arr|
arr.zip(arr).flatten[1..-2]},
:copy_inject_technique => lambda {|arr| copy = [];
arr.inject{|a,b| copy << a << b; b}; copy},
:flatten_compact_technique => lambda {|arr|
arr.zip(arr[1...-1]).flatten!.compact!},
:zip_concat_technique => lambda {|arr| arr.zip(arr).inject([])
{|n, e| n.concat(e)}[1..-2]},
:fill_technique => lambda {|arr| (Array.new((arr.length <<
1) - 2) {|i| arr[i >> 1]})[1..-2]},
:naive_technique => lambda do |arr|
a = Array.new((arr.length * 2) - 2)
a[0] = arr.first
a[a.length - 1] = arr.last
n = 1
1.upto(arr.length - 2) {|i| a[n] =
a[n+1] = arr
; n += 2}
a
end,
riginal_technique => lambda do |arr|
array_new = Array.new
arr.each {|e| array_new << e << e}
array_new.delete_at(0)
array_new.delete_at(array_new.size -
1)
array_new
end
}
n = 5000
array = ["a", 2, (0..1), /^$/, 1.2345, ["arr"] ] * 100
Benchmark.bmbm do |x|
techniques.each do |name, proc|
x.report(name.inspect) { n.times { proc.call(array) } }
end
end