3

I am adding up the elements from all of the nested lists, so far what I have is

for i in range(len(b)) :
    for j in range(len(b[i])):
        total = total + b[i][j]


But this will not work when an integer value exists in the nested list like,

b = [[1,2], [3,4], [5,6], 1]


In this case i am getting an error message that object of type 'int' has no len(). what should i do in this case?

Dan
  • 33
  • 1
  • 3
  • Does this answer your question? [sum of nested list in Python](https://stackoverflow.com/questions/14917092/sum-of-nested-list-in-python) – Georgy Jun 14 '21 at 14:04

5 Answers5

7

First of all, you are showing a common anti-pattern for Python programmers, don't loop over indices, loop over the objects themselves. E.g:

for item in b:
    do_something(item)

Rather than:

for i in range(len(b)):
    do_something(b[i])

It is clearer, simpler and faster.

That said, the main problem you are having is that one of the items isn't a list, so it doesn't have a length.

A better option here is to flatten the list with a generator expression and itertools.chain.from_iterable(), and then use the sum() builtin function to sum the elements.

>>> import collections
>>> import itertools
>>> b = [[1,2], [3,4], [5,6], 1]
>>> list(itertools.chain.from_iterable(item if isinstance(item, collections.Iterable) else [item] for item in b))
[1, 2, 3, 4, 5, 6, 1]
>>> sum(itertools.chain.from_iterable(item if isinstance(item, collections.Iterable) else [item] for item in b))
22

We need the generator expression as itertools.chain() won't handle non-iterable items, so we place any into a list to work around this.

An alternative would be to make your own generator:

def chain_mixed(iterable):
    for item in iterable:
        try:
            for subitem in item:
                yield subitem
        except TypeError:
            yield item

Then you could simply do:

sum(chain_mixed(b))
Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • Nicely done - I'd write it like that except I would use `item if isinstance(item, collections.Iterable) else [item]` – Jon Clements Jul 12 '12 at 18:26
  • I am new in Python world so I didn't get half of your code, but Thanks a lot for marking anti pattern used by me and introducing me to generator expression and list comprehension :) – Dan Jul 12 '12 at 18:29
  • @JonClements Good idea, changed. – Gareth Latty Jul 12 '12 at 18:31
  • 1
    @Dan If you are new to list comps and generator expressions, I suggest you give [my tutorial video](https://www.youtube.com/watch?v=t85uBptTDYY) a watch. – Gareth Latty Jul 12 '12 at 18:33
  • @Lattyware : Thanks a lot for the video tutorial. – Dan Jul 12 '12 at 18:46
1

try something like this, use sum() only when the element is an list or tuple, else simple use the number.

>>> b = [[1,2], [3,4], [5,6], 1]
>>> sum(sum(x) if isinstance(x,(list,tuple)) else x for x in b)
22

improving your solution:

total=0
b = [[1,2], [3,4], [5,6], 1]
for i in range(len(b)) :
    if isinstance(b[i],(list,tuple)):
        for j in range(len(b[i])):
            total += b[i][j]
    else:
        total +=b[i]
print total  #prints 22
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • but it would still fail if there was another layer of lists in one of the sublists (ie `b= [[1,2,[1]],[3,4],[5,6],1]`) – Joran Beasley Jul 12 '12 at 18:18
  • @JoranBeasley as you can see from OP's approach he's only concerned with list of lists, not list of lists of lists. – Ashwini Chaudhary Jul 12 '12 at 18:22
  • @JoranBeasley That's a different problem. The question did not ask for arbitrarily nested lists and the solution given gives no indication of a need for such. – Gareth Latty Jul 12 '12 at 18:22
  • yeah I know I was just pointing it out... not saying it was incorrect or anything else( I gave both this and @Lattyware's solution +1) – Joran Beasley Jul 12 '12 at 18:26
  • Thanks Ashwini, isinstance() solves the problem. I should have remembered it at the very first place. – Dan Jul 12 '12 at 18:31
  • @ Joran, Thanks for adding one more level. – Dan Jul 12 '12 at 18:31
  • It's worth noting that checking `isinstance()` of the `tuple` and `list` classes is a bad idea as these are not the only iterables, making the solution less likely to work elsewhere. It's not wrong, but it's not as neat a solution, and, as type checking, it's unpythonic (for this reason). – Gareth Latty Jul 12 '12 at 18:34
1

a generator-based solution

>>> b = [[1,2], [3,4], [5,6], 1]
>>> def sum_up(x):
...     for i in x:
...             if isinstance(i, int):
...                     yield i
...             else:
...                     for j in sum_up(i):
...                             yield j
... 
>>> sum(sum_up(b))
22
>>> b = [[1,2], [3,4], [5,6,[3,[6,7]]], 1]
>>> sum(sum_up(b))
38
iruvar
  • 22,736
  • 7
  • 53
  • 82
0

one way to do it would be

def calc_sum(the_list):
    sum = 0
    for item in the_list:
        if isinstance(item,(list,tuple)):
           sum += calc_sum(item)
        else:
           sum += item
    return sum

not that pythonic ... but it should work

Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
0

Another way to do this

This will work if the list contains nested list and integers/floats Here I've used python inbuilt function 'sum' to add all the elements of a list

def add(nested_list):
    temp=[]
    for i in nested_list:
        if isinstance(i,list):
            temp.append(sum(i))
        else:
            temp.append(i)
    print sum(temp)