I want to write code that returns a new list where the ith element is the sum of the first i 1 elements of the original list. For example, for the list [1, 2, 3]
, the result is [1, 3, 6]
.
So I've written this:
def cumulative_sum(numbers: list[int]) -> list[int]:
"""Returns the cumulative sum of the given list of numbers."""
cum_sum = []
for t in numbers:
cum_sum.append(sum(numbers[:t]))
return cum_sum
print(cumulative_sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
However, when I run this I get [1, 18, 9, 13, 18, 24, 31, 39, 48, 58]
, where there is an inexplicable 18 and the sequence seems to only work after the first 3 values.
CodePudding user response:
You are mixing indexes and elements when iterating
You can do something like this:
def cumulative_sum(numbers: list[int]) -> list[int]:
"""Returns the cumulative sum of the given list of numbers."""
#initialize with the first element
cum_sum = [numbers[0]]
# start iterating with the second element
for i in range(1, len(numbers)):
# add the current element to the previous cumsum
cum_sum.append(cum_sum[-1] numbers[i])
return cum_sum
print(cumulative_sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
CodePudding user response:
It often makes sense to implement such functions as generator,
def cumulative_sum(numbers):
"""Returns the cumulative sum of the given list of numbers."""
total = 0
for t in numbers:
total = t
yield total
so you can loop over the result lazily for i in cumulative_sum([1, 2, 3]):
or turn it into a list by list(cumulative_sum([1, 2, 3]))
if you really need to. This function, however, is exactly the same as itertools.accumulate
so you might as well use that:
from itertools import accumulate
# [1, 3, 6]
print(list(accumulate([1, 2, 3])))