What happened to this total?

I am trying to get the result [1,3,6]. Am I missing something really obvious? The error I received is: IndexError: list index out of range

 def cumulative_sum(n): cum_sum = [] y = 0 for i in n: y += n[i] cum_sum.append(y) print cum_sum a = [1,2,3] cumulative_sum(a) 
+4
source share
5 answers
 def cumulative_sum(n): cum_sum = [] y = 0 for i in n: # <--- i will contain elements (not indices) from n y += i # <--- so you need to add i, not n[i] cum_sum.append(y) print cum_sum a = [1,2,3] cumulative_sum(a) 

Arrays are based on a null value in Python, so when you confuse n[i] with i , you get access to n[3] , and n only from 0 to 2.

+8
source

Problem with your loop:

 for i in n: y += n[i] 

The for loop iterates over n values, not indexes. Change y += n[i] to y += i .

An exception occurs on the third pass through the loop (when I am 3), since 3 is not within the boundaries of the array (real indices are [0-2]).

If you also want to iterate over indexes, you can use the built-in enumerate function:

 for i, x in enumerate(n): assert n[i] == x 
+7
source

Here is a simple generator-based implementation:

 def cumsum(seq): s= 0 for c in seq: s+= c yield s print [c for c in cumsum(range(7))] print [c for c in cumsum((0, 1, 2, 3, 4, 5, 6))] 

This IMHO is quite Putin's way of implementing cumsum.

But here is a more pragmatic implementation that allows you to process (all) all types where adding can make sense.

 def cumsum(seq): s= seq[0] for k in xrange(1, len(seq)): yield s s= s+ seq[k] yield s print [c for c in cumsum(range(7))] print [c for c in cumsum((0, 1, 2, 3, 4, 5, 6))] print [c for c in cumsum(['a', 'b', 'c'])] print [c for c in cumsum([['a'], ['b'], ['c']])] print [c for c in cumsum((('a', ), ('b', ), ('c', )))] 

Thus, all these examples behave as expected, which is not true for the Pythonic version. Try it yourself and find out the reason for the different behavior.

Update:
Based on the comments, there will be a more general cumsum:

 def cumsum(iterable): iterable= iter(iterable) s= iterable.next() yield s for c in iterable: s= s+ c yield s tests= [ [], [1], [1, 2], range(7), (0, 1, 2, 3, 4, 5, 6), ['a', 'b', 'c'], [['a'], ['b'], ['c']], (('a', ), ('b', ), ('c', )), xrange(7), ] for test in tests: print test, '=> ', list(cumsum(test)) 

Two more exits, but IMHO it is still very readable. And now the implementation focuses on what type of the first element iterable dictates, as expected that the addition will behave with the rest of the elements.

+6
source

Here is a fairly reliable function that works on any iterable objects that support + and in any Python since version 2.3 (just play with print and xrange so that the test infrastructure works with 3.x)

 Python 2.3.5 (#62, Feb 8 2005, 16:23:02) [MSC v.1200 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> def cumsum(iterable): ... first = True ... for v in iterable: ... if first: ... tot = v ... first = False ... else: ... tot = tot + v ... yield tot ... >>> def squares(start, stop): ... for i in xrange(start, stop): ... yield i * i ... >>> tests = [ ... [], ... [1], ... [1, 2], ... range(7), ... (0, 1, 2, 3, 4, 5, 6), ... ['a', 'b', 'c'], ... [['a'], ['b'], ['c']], ... (('a', ), ('b', ), ('c', )), ... squares(1, 5), ... ] >>> >>> for test in tests: ... print test, list(cumsum(test)) ... [] [] [1] [1] [1, 2] [1, 3] [0, 1, 2, 3, 4, 5, 6] [0, 1, 3, 6, 10, 15, 21] (0, 1, 2, 3, 4, 5, 6) [0, 1, 3, 6, 10, 15, 21] ['a', 'b', 'c'] ['a', 'ab', 'abc'] [['a'], ['b'], ['c']] [['a'], ['a', 'b'], ['a', 'b', 'c']] (('a',), ('b',), ('c',)) [('a',), ('a', 'b'), ('a', 'b', 'c')] <generator object at 0x014B6A58> [1, 5, 14, 30] >>> 
+1
source
 for I in n: # I will be an item from n y+=I 

or what you tried to do:

 for i in range(len(n)): # i is an int that you can index with y+=n[i] 
0
source

Source: https://habr.com/ru/post/1337680/


All Articles