user3927582
user3927582

Reputation: 189

Combining Arrays and Summing Integers

I'm working with multiple Arrays each with one string and many integers. I have managed to set together duplicates in nested arrays as I want to combine them. So as I loop over my parent array it outputs this:

[["word", 1, 1, 3, 4], ["word", 2, 1, 3, 4]] 

and another example:

[["without", 1, 1, 3, 4], ["without", 2, 1, 3, 4], ["without", 3, 1, 0, 0]]

I want a function to combine these into one array and sum the integers. So the first example above would become:

["word", 3, 2, 6, 8]

I have tried many different techniques like inject and reduce. My latest attempt isn't the most elegant:

# data is set of array
def inject_array(data)
  clicks = 0
  imps = 0
  cost = 0 
  converted_clicks = 0
  data.each do |i|
    clicks += i[1]
    i[1] = clicks
    imps += i[2]
    i[2] = imps
    cost += i[3]
    i[3] = cost
    converted_clicks += i[4]
    i[4] = converted_clicks
  end

It's getting a bit messy, is there a cleaner way?

Upvotes: 2

Views: 68

Answers (3)

wurde
wurde

Reputation: 2617

One way is to loop over the arrays, sum the parts, and rebuild.

word_array = [['word', 1, 1, 3, 4], ['word', 2, 1, 3, 4]]
puts "Squashing #{word_array}..."
i1 = 0
i2 = 0
i3 = 0
i4 = 0
word_array.each do |arr|
  i1 += arr[1]
  i2 += arr[2]
  i3 += arr[3]
  i4 += arr[4]
end
puts ['word', i1, i2, i3, i4].inspect

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110675

You can also methods of the class Matrix. Recall that to sum each column of a matrix with r rows, you pre-multiply the matrix by a row vector comprised of r 1s:

require 'matrix'

a = [["word", 1, 1, 3, 4], ["word", 2, 1, 3, 4]]

[a.first.first, (Matrix[[1]*a.size] * Matrix[*a.map { |e| e[1..-1] }]).to_a.first]
   #=> ["word", [3, 2, 6, 8]]

Upvotes: 0

Chris Heald
Chris Heald

Reputation: 62648

Assuming that the arrays will always be the same length, you can use Array#transpose to transpose your array of arrays from row-based to column-based arrays:

[["word", 1, 1, 3, 4], ["word", 2, 1, 3, 4]].transpose
 => [["word", "word"], [1, 2], [1, 1], [3, 3], [4, 4]]

From there, it's trivial enough to sum the numbers in each:

[["word", 1, 1, 3, 4], ["word", 2, 1, 3, 4]].transpose.map.with_index do |e, i|
  i == 0 ? e.first : e.inject(:+)
end # => ["word", 3, 2, 6, 8]

Upvotes: 4

Related Questions