1
\$\begingroup\$

I was writing a function in python to extract original values given a list containing cumulative sum values. For eg -

Given : cumulative_sum = [1, 3, 6, 10, 15, 21, 28, 36, 45]
Output : [1, 2, 3, 4, 5, 6, 7, 8, 9]

I came up with two functions A & B and am looking for feedback on them, especially using xrange() vs enumerate().

import numpy as np
cumulative = np.cumsum(range(1,10))

def A(cumulative):
    output = [0] * len(cumulative)
    for i in xrange(len(cumulative)-1):
        output[-(i+1)] = cumulative[-(i+1)] - cumulative[-(i+2)]
    output[0] = cumulative[0]
return output

def B(cumulative):
    output = [0] * len(cumulative)
    for i,e in reversed(list(enumerate(cumulative))):
        output[i]=cumulative[i] - cumulative[i-1]
    output[0]=cumulative[0]
return output
\$\endgroup\$
3
\$\begingroup\$

Both aren't great. B is really complicated, which is unnecessary. A has this extra negation:

output[-(i+1)] = cumulative[-(i+1)] - cumulative[-(i+2)]

You could have just used positive indices (why iterate backwards anyway?):

output[i+1] = cumulative[i+1] - cumulative[i]

I think sort of thing is best accomplished with itertools. In particular, there's a pairwise recipe:

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Which translates directly into what we want to do:

def C(cumulative):
    yield cumulative[0]
    for a, b in pairwise(cumulative):
        yield b-a

This returns a generator, instead of a list, but generators are typically far more useful anyway. I feel that this approach makes it much more explicit what it is you're actually doing: you're yielding the first element, and then the pairwise difference between the rest.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.