Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ruby: sum corresponding members of two or more arrays

Tags:

arrays

ruby

sum

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.

like image 644
jjnevis Avatar asked Apr 21 '10 11:04

jjnevis


4 Answers

Here's the transpose version Anurag suggested:

[[1,2,3], [4,5,6]].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...

like image 128
glenn mcdonald Avatar answered Nov 13 '22 04:11

glenn mcdonald


Now we can use sum in 2.4

nums = [[1, 2, 3], [4, 5, 6]]
nums.transpose.map(&:sum) #=> [5, 7, 9]
like image 43
cavin kwon Avatar answered Nov 13 '22 05:11

cavin kwon


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] ]
arr.inject(&:+)
=> 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]
like image 11
Abdo Avatar answered Nov 13 '22 04:11

Abdo


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.

like image 7
Anurag Avatar answered Nov 13 '22 04:11

Anurag