Reputation: 53
I have a list of groups:
[[10, 1], [11, 1], [13, 3], [15, 10]]
I need to calculate cumulative sum for them, to get:
[[10, 1], [11, 2], [13, 5], [15, 15]]
.
Been trying with Enum.reduce
but I do not know yet how to return new list as an accumulator, should I take tail of the list to get the last group and take the last amount from it or there's a better way?
Upvotes: 3
Views: 1372
Reputation: 5812
Maybe I didn't get your point, so I prepared two answers based on exactly what you need.
1. List of lists, second value is cumulative sum
Solution without Enum.scan
proposed by Dogbert, which is awesome one.
def map_cumulative_sum(list) do
list
|> do_map_cumulative_sum([], 0)
end
defp do_map_cumulative_sum([], acc, _sum_y) do
Enum.reverse(acc)
end
defp do_map_cumulative_sum([[x, y] | t], acc, sum_y) do
sum_y = y + sum_y
do_map_cumulative_sum(t, [ [ x, sum_y] | acc], sum_y)
end
2. Single list with result
In this case Enum.reduce
will do the job.
You can use version with or without accumulator (accumulator in this case would be first element of your list):
list = [[10, 1], [11, 1], [13, 3], [15, 10]]
# reduce list of lists to one list, where 2nd value is cumulative sum
Enum.reduce(list, fn([x, y], [acc_x, acc_y]) -> [x, y + acc_y] end)
> [15, 15]
Version with explicit accumulator will just have [0, 0] as second argument for Enum.reduce
:
Enum.reduce(list, [0, 0], fn([x, y], [acc_x, acc_y]) -> [x, y + acc_y] end)
Upvotes: 0
Reputation: 222358
This is the perfect use case for Enum.scan/2
since you want to collect the value of each reduction:
[[10, 1], [11, 1], [13, 3], [15, 10]]
|> Enum.scan(fn [a, b], [_c, d] ->
[a, b + d]
end)
|> IO.inspect
Output:
[[10, 1], [11, 2], [13, 5], [15, 15]]
Upvotes: 8