2

I have a list with numbers in it and I would like to sum different parts (in successive order) of that list and store those values in a new list.

Example:

a = [0, 1, 2, 3, 4, 5]
b = []
b.append(a[0])
b.append(a[0] + a[1])
b.append(a[0] + a[1] + a[2])

Of course the list I have is much longer so I would assume I need a for loop, but I am unsure how to proceed.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
JForsythe
  • 758
  • 1
  • 7
  • 12
  • 1
    You could use sum(). For instance sum(a[3:]) will sum the third element of the list until the end – dgsleeps Mar 26 '15 at 01:56

4 Answers4

8

You can use a simple list comprehension, with slicing and sum function, like this

>>> a = [0, 1, 2, 3, 4, 5]
>>> [sum(a[:i + 1]) for i in xrange(len(a))]
[0, 1, 3, 6, 10, 15]

Note: As paxdiablo and DSM noted, this method will be highly inefficient, as it has to find the sum of all the numbers which were seen before, again and again (for example, when you find sum of first 4 elements, you would be computing sum of first three elements as well, and implicitly sum of 2 elements as well). So, this is not suitable for larger lists.

The best way to solve this is by accumulating the results in a temporary variable and store it in the list like this

>>> result, temp = [], 0
>>> for item in a:
...     temp += item
...     result.append(temp)
...     
>>> result
[0, 1, 3, 6, 10, 15]

Actually, if you are going to iterate over the sums and if the actual list is very big, then you can better make it as a generator function, like this

>>> def accumulate_sum(input_list):
...     temp = 0
...     for item in input_list:
...         temp += item
...         yield temp
...     

and then iterate it to get the values one by one, like this

>>> for item in accumulate_sum([0, 1, 2, 3, 4, 5]):
...     print(item)
...     
0
1
3
6
10
15

You can also get the entire list, with list function, like this

>>> list(accumulate_sum([0, 1, 2, 3, 4, 5]))
[0, 1, 3, 6, 10, 15]

FYI, Python 3.2+ has a function called itertools.accumulate, which can be used like this

>>> from itertools import accumulate
>>> from operator import add
>>> a = [0, 1, 2, 3, 4, 5]
>>> list(accumulate(a, func=add))
[0, 1, 3, 6, 10, 15]

Or you can pass your own function which adds two numbers to accumulate, like this

>>> list(accumulate([0, 1, 2, 3, 4, 5], func=lambda x, y: x + y))
[0, 1, 3, 6, 10, 15]
Community
  • 1
  • 1
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • It appears to me the first code block would be fairly inefficient, given it's calculating sums of the same values multiple times. For small lists it probably won't matter but I suspect the second block would be faster. – paxdiablo Mar 26 '15 at 02:18
  • @paxdiablo True, I included a note about that and generator version also. – thefourtheye Mar 26 '15 at 02:28
4

This is called a cumulative sum and there is a function in numpy for the job:

>>> import numpy as np
>>> a = [0, 1, 2, 3, 4, 5]
>>> np.cumsum(a)
array([ 0,  1,  3,  6, 10, 15])
wim
  • 338,267
  • 99
  • 616
  • 750
1
a = range(6) # or however you want to generate your data
b = [a[0]] # start with first element so we always have a previous element in the loop
for v in a[1:]:
   b.append(v+b[-1]) # the last element of b contains the sum of all the previous numbers
Foon
  • 6,148
  • 11
  • 40
  • 42
  • 1
    I think that second line should be `b = a[0]` - it's just a coincidence that both OPs and your test data have `0` as the first element. – paxdiablo Mar 26 '15 at 02:20
  • True enough, should have been explicit about it – Foon Mar 26 '15 at 02:21
  • Oops, yes, and you fixed my error as well, obviously it should have been a _list_ with `a[0]` in it rather than just `a[0]`. – paxdiablo Mar 26 '15 at 02:27
0

Why not take your list and turn it into an array and then sum. The code would look something like this:

    import numpy as np
    a = [0,1,2,3,4]
    b = np.array(a)
    c = []
    for i in range(len(a)):
        c.append(np.sum(b[0:i+1]))
jfish003
  • 1,232
  • 8
  • 12