How to find the cumulative sum of numbers in a list?

前端 未结 21 1595
挽巷
挽巷 2020-11-22 02:09
time_interval = [4, 6, 12]

I want to sum up the numbers like [4, 4+6, 4+6+12] in order to get the list t = [4, 10, 22].

相关标签:
21条回答
  • 2020-11-22 02:38

    Behold:

    a = [4, 6, 12]
    reduce(lambda c, x: c + [c[-1] + x], a, [0])[1:]
    

    Will output (as expected):

    [4, 10, 22]
    
    0 讨论(0)
  • 2020-11-22 02:41

    Here's another fun solution. This takes advantage of the locals() dict of a comprehension, i.e. local variables generated inside the list comprehension scope:

    >>> [locals().setdefault(i, (elem + locals().get(i-1, 0))) for i, elem 
         in enumerate(time_interval)]
    [4, 10, 22]
    

    Here's what the locals() looks for each iteration:

    >>> [[locals().setdefault(i, (elem + locals().get(i-1, 0))), locals().copy()][1] 
         for i, elem in enumerate(time_interval)]
    [{'.0': <enumerate at 0x21f21f7fc80>, 'i': 0, 'elem': 4, 0: 4},
     {'.0': <enumerate at 0x21f21f7fc80>, 'i': 1, 'elem': 6, 0: 4, 1: 10},
     {'.0': <enumerate at 0x21f21f7fc80>, 'i': 2, 'elem': 12, 0: 4, 1: 10, 2: 22}]
    

    Performance is not terrible for small lists:

    >>> %timeit list(accumulate([4, 6, 12]))
    387 ns ± 7.53 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    
    >>> %timeit np.cumsum([4, 6, 12])
    5.31 µs ± 67.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    >>> %timeit [locals().setdefault(i, (e + locals().get(i-1,0))) for i,e in enumerate(time_interval)]
    1.57 µs ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    

    And obviously falls flat for larger lists.

    >>> l = list(range(1_000_000))
    >>> %timeit list(accumulate(l))
    95.1 ms ± 5.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    >>> %timeit np.cumsum(l)
    79.3 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    >>> %timeit np.cumsum(l).tolist()
    120 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    >>> %timeit [locals().setdefault(i, (e + locals().get(i-1, 0))) for i, e in enumerate(l)]
    660 ms ± 5.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    Even though the method is ugly and not practical, it sure is fun.

    0 讨论(0)
  • 2020-11-22 02:42

    In Python3, To find the cumulative sum of a list where the ith element is the sum of the first i+1 elements from the original list, you may do:

    a = [4 , 6 , 12]
    b = []
    for i in range(0,len(a)):
        b.append(sum(a[:i+1]))
    print(b)
    

    OR you may use list comprehension:

    b = [sum(a[:x+1]) for x in range(0,len(a))]
    

    Output

    [4,10,22]
    
    0 讨论(0)
  • 2020-11-22 02:42

    A pure python oneliner for cumulative sum:

    cumsum = lambda X: X[:1] + cumsum([X[0]+X[1]] + X[2:]) if X[1:] else X
    

    This is a recursive version inspired by recursive cumulative sums. Some explanations:

    1. The first term X[:1] is a list containing the previous element and is almost the same as [X[0]] (which would complain for empty lists).
    2. The recursive cumsum call in the second term processes the current element [1] and remaining list whose length will be reduced by one.
    3. if X[1:] is shorter for if len(X)>1.

    Test:

    cumsum([4,6,12])
    #[4, 10, 22]
    
    cumsum([])
    #[]
    

    And simular for cumulative product:

    cumprod = lambda X: X[:1] + cumprod([X[0]*X[1]] + X[2:]) if X[1:] else X
    

    Test:

    cumprod([4,6,12])
    #[4, 24, 288]
    
    0 讨论(0)
  • 2020-11-22 02:43

    There could be many answers for this depending on the length of the list and the performance. One very simple way which I can think without thinking of the performance is this:

    a = [1, 2, 3, 4]
    a = [sum(a[0:x:1]) for x in range(len(a)+1)][1:]
    print(a)
    

    [1, 3, 6, 10]

    This is by using list comprehension and this may work fairly well it is just that here I am adding over the subarray many times, you could possibly improvise on this and make it simple!

    Cheers to your endeavor!

    0 讨论(0)
  • 2020-11-22 02:44

    First, you want a running list of subsequences:

    subseqs = (seq[:i] for i in range(1, len(seq)+1))
    

    Then you just call sum on each subsequence:

    sums = [sum(subseq) for subseq in subseqs]
    

    (This isn't the most efficient way to do it, because you're adding all of the prefixes repeatedly. But that probably won't matter for most use cases, and it's easier to understand if you don't have to think of the running totals.)

    If you're using Python 3.2 or newer, you can use itertools.accumulate to do it for you:

    sums = itertools.accumulate(seq)
    

    And if you're using 3.1 or earlier, you can just copy the "equivalent to" source straight out of the docs (except for changing next(it) to it.next() for 2.5 and earlier).

    0 讨论(0)
提交回复
热议问题