Take the 2-minute tour ×

I've got two (or more) arrays with 12 integers in each (corresponding to values for each month). All I want is to add them together so that I've got a single array with summed values for each month. Here's an example with three values: [1,2,3] and [4,5,6] => [5,7,9]

The best I could come up with was:

[[1,2,3],[4,5,6]].transpose.map{|arr| arr.inject{|sum, element| sum+element}} #=> [5,7,9]

Is there a better way of doing this? It just seems such a basic thing to want to do.

share|improve this question

6 Answers 6

up vote 24 down vote accepted

Here's the transpose version Anurag suggested:

a.transpose.map {|x| x.reduce(:+)}

This will work with any number of component arrays. reduce and inject are synonyms, but reduce seems to me to more clearly communicate the code's intent here...

share|improve this answer
... or in rails: a.transpose.map {|x| x.sum} –  jjnevis Apr 21 '10 at 12:59
@jjnevis: well, if we're golfing it, how about a.transpose.map(&:sum) –  rampion Apr 21 '10 at 18:25
@rampion: That's certainly quite terse - could you explain the (&:sum) bit? Thanks –  jjnevis Apr 22 '10 at 7:28
@jjnevis: So, Symbol#to_proc returns a Proc that passes that symbol to its argument (so :sum.to_proc returns lambda {|x| x.sum}). An & prefix-operator for the last argument to a method invokes #to_proc on the argument, and passes the resulting Proc as a block to the method. This allows you to write methods that capture their block arguments (def foo(a,b,&block)...end) and pass them into whatever methods they may call (bar = baz(1, &block)). It also allows this trickery with symbols, since a.transpose.map(&:sum) is the equivalent of your rails solution. –  rampion Apr 23 '10 at 14:30
But note that in 1.9 reduce takes a symbol directly, thus the :+ there instead of needing &:+... –  glenn mcdonald Apr 24 '10 at 2:35

here's my attempt at code-golfing this thing:

// ruby 1.9 syntax, too bad they didn't add a sum() function afaik
[1,2,3].zip([4,5,6]).map {|a| a.inject(:+)} # [5,7,9]

zip returns [1,4], [2,5], [3,6], and map sums each sub-array.

share|improve this answer
Nice. How would this work with three or more arrays - I'm iterating over an unknown number of arrays, so the transpose works well because I can just push them into an empty array and transpose that. I love the ':+' syntax for inject (although not as good as a sum() method as you say, rails does add it, though)- not see that before, thanks. –  jjnevis Apr 21 '10 at 11:52
zip is a method of Array, and it accepts any number of arrays as parameters. But I don't know how would you pass those if they were created dynamically. transpose seems like a better choice for that. Ruby generally covers many of the commonly used functions, but where is lacks, Rails comes to rescue! –  Anurag Apr 21 '10 at 11:58
say aoa is our array of arrays, and you want to calculate [ aoa[0][0] + aoa[1][0] + ... + aoa[-1][0], aoa[0][1] + aoa[1][1] + ... + aoa[-1][1], ..., aoa[0][-1] + aoa[1][-1] + ... + aoa[-1][-1] ] then you could do first, *rest = *aoa; first.zip(*rest).map { |a| a.inject(&:+) } –  rampion Apr 21 '10 at 18:22
I think that arr.zip(arr).map { |a,b| a + b } is more readable than using inject/reduce over a 2 element array. –  MrPopinjay Sep 17 at 10:11
[[1,2,3],[4,5,6]].transpose.map{|a| a.sum} #=> [5,7,9]
share|improve this answer
Note that this doesn't work in plain Ruby. Maybe it does in Rails, as suggested by jjnevis. –  FriendFX Dec 18 '13 at 4:35

For clearer syntax (not the fastest), you can make use of Vector:

require 'matrix'
Vector[1,2,3] + Vector[4,5,6]
=> Vector[5, 7, 9]

For multiple vectors, you can do:

arr = [ Vector[1,2,3], Vector[4,5,6], Vector[7,8,9] ]
=> Vector[12, 15, 18]

If you wish to load your arrays into Vectors and sum:

arrays = [ [1,2,3], [4,5,6], [7,8,9] ]
arrays.map { |a| Vector[*a] }.inject(:+)
=> Vector[12, 15, 18]
share|improve this answer

@FriendFX, you are correct about @user2061694 answer. It only worked in Rails environment for me. You can make it run in plain Ruby if you make the following changes...

In the IRB

[[0, 0, 0], [2, 2, 1], [1,3,4]].transpose.map {|a| a.inject(:+)}
 => [3, 5, 5]

[[1,2,3],[4,5,6]].transpose.map {|a| a.inject(:+)}
 => [5, 7, 9]
share|improve this answer

This might not be the best answer but it works.

array_one = [1,2,3]
array_two = [4,5,6]
x = 0
array_three = []
while x < array_one.length
  array_three[x] = array_one[x] + array_two[x]
  x += 1


This might be more lines of code than other answers, but it is an answer nonetheless

share|improve this answer
I like this one simply because it's very clear what's going on, but you can clean it up a bit by using "array_one.each_index do |x|" –  jjnevis Sep 29 at 8:39

Your Answer


