11

can you help me with code which returns partial sum of numbers in text file? I must import text file, then make a code for partial sums without tools ..etc.

My input:

4
13
23
21
11

The output should be (without brackets or commas):

4 
17
40
61 
72

I was trying to make code in python, but could only do total sum and not partial one. If i use the += operator for generator, it gives me an error!

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
user1798558
  • 107
  • 1
  • 1
  • 5

7 Answers7

25

Well, since everyone seems to be giving their favourite idiom for solving the problem, how about itertools.accumulate in Python 3:

>>> import itertools
>>> nums = [4, 13, 23, 21, 11]
>>> list(itertools.accumulate(nums))
[4, 17, 40, 61, 72]
DSM
  • 342,061
  • 65
  • 592
  • 494
  • Note: "new in version 3.2". Interesting addition. :) – Andy Hayden Nov 04 '12 at 19:37
  • 2
    @hayden: it's even better in 3.3. 3.2 doesn't accept a function parameter. – DSM Nov 04 '12 at 19:38
  • I particularly like how `total = next(it)` deals with the `[]` case... – Andy Hayden Nov 04 '12 at 19:41
  • 1
    Wow, I didn't know they were adding this. Too bad the 3.3 version has `func` as the _second_ argument -- I would have expected them to make it consistent with `map` and `reduce` (and almost all the other itertools functions that accept functions as arguments). – senderle Nov 04 '12 at 19:47
  • It should be printed output ( without brackets ), and for some to me unknown reason i cant import itertools. Can it be done any other way? – user1798558 Nov 04 '12 at 20:10
  • @DSM I can't wait! @senderle consistency is one argument, but frequency of use is another - you always need a function to `map` or `reduce` and there is really no meaningful default, but `accumulate` will normally be used for partial sums. – Karl Knechtel Nov 04 '12 at 20:19
13

There are a number of ways to create your sequence of partial sums. I think the most elegant is to use a generator.

def partial_sums(iterable):
    total = 0
    for i in iterable:
        total += i
        yield total

You can run it like this:

nums = [4, 13, 23, 21, 11]
sums = list(partial_sums(nums)) # [ 4, 17, 40, 61, 72]

Edit To read the data values from your file, you can use another generator, and chain them together. Here's how I'd do it:

with open("filename.in") as f_in:
    # Sums generator that "feeds" from a generator expression that reads the file
    sums = partial_sums(int(line) for line in f_in)

    # Do output:
    for value in sums:
        print(value)

    # If you need to write to a file, comment the loop above and uncomment this:
    # with open("filename.out", "w") as f_out:
    #    f_out.writelines("%d\n" % value for value in sums)
Ruslan Bes
  • 2,715
  • 2
  • 25
  • 32
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • This is probably the most useful answer for the OP. – DSM Nov 04 '12 at 23:47
  • @user1798558: if this answer helped you, you can thank the author by selecting the green checkmark on the left (see [here](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) for instructions.) – DSM Nov 05 '12 at 02:56
5

numpy.cumsum will do what you want.

If you're not using numpy, you can write your own.

def cumsum(i):
    s = 0
    for elt in i:
        s += elt
        yield s
Katriel
  • 120,462
  • 19
  • 136
  • 170
2

try this:

import numpy as np

input = [ 4, 13, 23, 21, 11 ]
output = []
output.append(input[0])
for i in np.arange(1,len(input)):
    output.append(input[i] + input[i-1])

print output
arc46
  • 21
  • 3
2

Use cumulative sum in numpy:

import numpy as np
input = np.array([4, 13, 23, 21 ,11])
output = input.cumsum()

Result:

print output
>>>array([ 4, 17, 40, 61, 72])

Or if you need a list, you may convert output to list:

output = list(output)
print output
>>>[4, 17, 40, 61, 72]
ojy
  • 2,402
  • 2
  • 18
  • 23
1

something like this:

>>> lst = [4, 13, 23, 21 ,11]
>>> [sum(lst[:i+1]) for i, x in enumerate(lst)]
[4, 17, 40, 61, 72]
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 6
    -1 This computes `sum([4])`, then `sum([4,13])`, then `sum([4,13,23])`, etc -- defeating the point of taking a cumulative sum! – Katriel Nov 04 '12 at 19:18
  • 7
    I wouldn't say that it defeats the purpose. It's an inefficient way to compute it (O(n^2) instead of O(n)) but it gets the right answer. – DSM Nov 04 '12 at 19:29
1

This is an alternative solution using reduce:

nums = [4, 13, 23, 21, 11]
partial_sum = lambda a, b: a + [a[-1] + b]
sums = reduce(partial_sum, nums[1:], nums[0:1])

Pluses in lambda are not the same operator, the first one is list concatenation and the second one is sum of two integers. Altough Blckknght's may be more clear, this one is shorter and works in Python 2.7.

Slaven Glumac
  • 543
  • 9
  • 19