Home > OS >  Accumulate sum of all element in list having integers
Accumulate sum of all element in list having integers

Time:03-05

I'm trying to get the sum of all numbers for each list through itertool accumulate function: This is the code:

from itertools import *
import operator

list_numbers = [[45,43,56,67],[41,423,526,627,897],[545,453,656,667]]

Iterable_list = iter(list_numbers)

while(True):
    try:
        print(list(accumulate(next(Iterable_list),operator.add))[-1])
    except StopIteration as ex:
        print(ex)
        break

The above works well.

if I try to take out the max of each list:

while(True):
    try:
        print(list(accumulate(next(Iterable_list),func=max))[-1])
    except StopIteration as ex:
        print(ex)
        break

this also works well.

My interpretation was, if I use func = sum, it will do the sum of each list like I tried below but it prompts error message:

'int' object is not iterable


while(True):
    try:
        print(list(accumulate(next(Iterable_list),func=sum))[-1])
    except StopIteration as ex:
        print(ex)
        break

Why it doesn't it work and in which scenario can we use func = sum?

CodePudding user response:

You could understand better the behavior of itertools.accumulate if you use a lambda function to explore the inputs that func will receive.

Let's use lambda x: print(x) instead of sum first, to print the values:

TypeError: <lambda>() takes 1 positional argument but 2 were given

Ok, so func will receive two values. Let's try lambda x, y: print(x, y):

45 43
None 56
None 67
None
41 423
None 526
None 627
None 897
None
545 453
None 656
None 667
None

Why are we seeing None? Because print() does not return any value, so it returns a None.

This means that func should receive two values from the iterator (L1 and L2), apply an operation on both values and return a single value C. Then, apply the same operation on the previous result (C) with the next value in the iterator (L3).


Why sum() fails?

Well, because it expects a single argument, an iterable, and optionally accepts a second (start). Now, itertools.accumulate is passing two values and Python assumes you're trying to use sum(L1, start=L2), but L1 is not iterable since its just a number... TypeError: 'int' object is not iterable.

In which scenario can we use func=sum?

sum() could help us if it could receive two values and return a single one, which is possible (sum(iterable, start=start)). Now, consider that the output of sum will be used as the first input of sum with the next element in the iterable, something like: sum(sum(L1, start=L2), start=L3) and so on. This means that sum(L1, start=L2) should return an iterable for us to be able to use sum. It's hard to find an example for this, meaning that sum might not be the best option for any particular case when using itertools.accumulate, but this doesn't mean that sum is not useful by itself.

CodePudding user response:

This can be done using Zip() or map() method or using numpy.

Using zip():

def nested_sum(lst):
      
 return [sum(i) for i in zip(*lst)]
      
lst = [[2, 4, 6], [2, 2, 1], [1, 2, 3]] # A Sample List
print(nested_sum(lst))

#Output
[12,5,6]
  • Related