Cumulative Array Sum in Ruby

Cumulative array sum in Ruby


class Array
def cumulative_sum
sum = 0
self.map{|x| sum += x}
end
end

How do I add a cumulative sum to an array for only one value?

Yes, this is possible in Ruby. You can use [map][1] and do something like this:

sum = 0
array.map {|x,y| [x, (sum+=y)]}

This is how it works. For the given the input:

array = ["one", 1], ["two", 2]

It will iterate through each of the elements in the array e.g.) the first element would be ["one", 1].

It will then take that element (which is an array itself) and assign the variable x to the first element in that array e.g.) "one" and y to the second e.g.) 1.

Finally, it will return an array with the result like this:

=> ["one", 1], ["two", 3]

Cumulative inverse array sum in Ruby

As you mentioned efficient, I am not following your code of map.with_index way: it have time complexity of O(n^2)

Inverse cumulative_sum can be done with cumulative_sum and 2 reverse:

# cumulative sum with O(n) complexity
# from http://stackoverflow.com/a/1475845/327815
class Array
def cumulative_sum
sum = 0
self.map{|x| sum += x}
end
end

array = [50, 40, 30, 20]
p array.reverse.cumulative_sum.reverse

Calculate running total of multiple values in Ruby

UPDATE1:

it doesn't change anything.
You can still apply the codes.

(0..3).each do |value|
# First loop
values << [4444.33,0,333.444,0]
# Second loop
values << [3333.444,0,1123.44,5444]
# Third loop
values << [321112.4,443.3,0,4444]
# Here I need to add each array with the next one
values.transpose.map {|x| x.reduce(0, :+)}
end



1st ANSWER:

use mapping. just one line.

values.transpose.map {|x| x.reduce(0, :+)}

How can I convert this array so that each element represents the cumulative value of the previous elements?


s = 0
[20, 25, 40, 60].map{|e| s += e}

Ruby compute cumulative sum from endpoints recursively?


def sum_cumulative_recursive(a,b)
return a if a == b
a, b = [a,b].sort
a + sum_cumulative_recursive(a + 1, b)
end

EDIT

Here is the most efficient solution I could see from some informal benchmarks:

def sum_cumulative_recursive(a,b)
return a if a == b
a, b = b, a if a > b
a + sum_cumulative_recursive(a + 1, b)
end

Using:

Benchmark.measure { sum_cumulative_recursive(14,139) }

Benchmark for my initial response: 0.005733

Benchmark for @Ajedi32's response: 0.000371

Benchmark for my new response: 0.000115

I was also surprised to see that in some cases, the recursive solution approaches or exceeds the efficiency of the more natural inject solution:

Benchmark.measure { 10.times { (1000..5000).inject(:+) } }
# => 0.010000 0.000000 0.010000 ( 0.027827)

Benchmark.measure { 10.times { sum_cumulative_recursive(1000,5000) } }
# => 0.010000 0.010000 0.020000 ( 0.019441)

Though you run into stack level too deep errors if you take it too far...

How to calculate running total of array elements?

Here's a one-liner. The to_i is necessary to handle the first element where the result array is empty (nil.to_i will evaluate to 0).

@user_trans.inject([]) { |result, element| result << result.last.to_i + element }

Ruby diff two hashes and merge in loop with cumulative sum

I will not try to implement your logic, but dealing with hashes is what I will try to elucidate. For the sake of simplicity, I haven't looped, but just dealt with test data

domains = ['domain1','domain2','domain3']

h1 = {}
h2 = {}
# generate blank template for each domain
domains.each { |vhostname|
h1[vhostname] ||= { :utime => 0, :last_seen => 0, :process_count => 0, :process_count_avg => 0 }
h2[vhostname] ||= {}
}

# dummy loop
1.upto(5) {
h3={}
# start collecting data for each domain
domains.each { |vhostname|
# TEST DATA
h3[vhostname] ||= {}
1.upto(5) {
_pid = rand(1..10)
h3[vhostname][:"#{_pid}"] ||= {:utime => rand(9999)}
}
# TEST DATA

h2[vhostname].merge!(h3[vhostname])
h2[vhostname].each { |proc, details|
unless h3[vhostname].key?(proc)
h1[vhostname][:utime] = h1[vhostname][:utime] + details[:utime]
end
}
h2[vhostname] = h2[vhostname].keep_if { |proc| h3[vhostname].key?(proc)}
}
}


Related Topics



Leave a reply



Submit