Reputation: 25642
Say I have the following two arrays:
a = [1, 0, 2, 1, 6]
b = [0, 5, 5, 6, 1]
I want to create (or modify a or b) an array with the values inside each relative index of the array to be added together, like:
[1, 5, 7, 7, 7]
Is there a elegant (and fast) way to do this without looping over every index in the first array and adding from the second. I have a feeling that map/reduce/inject might be a way to go here, but these methods have always seemed a bit "magical" to me and I never really understood them.
Upvotes: 2
Views: 400
Reputation: 1754
This is one of the thing you could do.
[[4,5,6], [10,25,16]].transpose.map {|x| x.reduce(:+)}
Even inject
would also do the same.
[[10,20,30],[24,52,62]].transpose.map {|a| a.inject(:+)}
and to have more understanding. Please have a look at ruby: sum corresponding members of two or more arrays
Upvotes: 4
Reputation: 9497
All bases seem to be covered by other answers. These are submitted for interest only:
c = b.cycle
#=> #<Enumerator: [0, 5, 5, 6, 1]:cycle>
a.map { |e| e + c.next }
#=> [1, 5, 7, 7, 7]
And another way:
a.map { |e| e + b.rotate!.last }
#=> [1, 5, 7, 7, 7]
BENCHMARKS
Benchmarks (which I am not doing myself any favours by showing) for larger arrays.
require 'fruity'
a = (1..10_000).to_a.shuffle
b = a.shuffle
compare do
sagar { ar = a.dup; br = b.dup; c = br.cycle; ar.map { |e| e + c.next } }
sagar_2 { ar = a.dup; br = b.dup; ar.map { |e| e + br.rotate!.last } }
cary { ar = a.dup; br = b.dup; ar.each_index.map { |i| ar[i]+br[i] } }
surya { ar = a.dup; br = b.dup; ar.zip(br).map{|v| v.reduce(:+) } }
surya_2 { ar = a.dup; br = b.dup; ar.map.with_index { |v, i| v + br[i] } }
sinsuren { ar = a.dup; br = b.dup; [ar, br].transpose.map {|x| x.reduce(:+)} }
flamine { ar = a.dup; br = b.dup; ar.map{|i| br.shift.to_i + i }}
stefan { ar = a.dup; br = b.dup; ar.zip(br).map { |i, j| i + j }}
end
#Running each test once. Test will take about 3 seconds.
#flamine is similar to surya_2
#surya_2 is similar to stefan
#stefan is similar to cary
#cary is faster than sinsuren by 3x ± 1.0
#sinsuren is similar to surya
#surya is faster than sagar by 2x ± 0.1
#sagar is faster than sagar_2 by 15x ± 1.0
Ran this a few times, sometimes flamine is outright fastest: flamine is faster than surya_2 by 10.000000000000009% ± 10.0%
. The caveat being that flamine's technique modifies b
to an empty array.
Upvotes: 4
Reputation: 487
I like this variant, but its work correctly only if a.size >= b.size
a.map{|i| b.shift.to_i + i }
Upvotes: 1
Reputation: 15992
You could zip
and then use reduce
:
p a.zip(b).map{|v| v.reduce(:+) }
#=> [1, 5, 7, 7, 7]
Or, if you're sure that array a
and b
will always be of equal length:
p a.map.with_index { |v, i| v + b[i] }
#=> [1, 5, 7, 7, 7]
Upvotes: 7