0

Here is a small piece of Python code to add elements of a nested list:

def nested_sum(lists):
    s = [0,0,0,0,0,0,0,0]  # If I delete this line then an error is given
    for i in range(len(lists)):
        s[i] = sum(lists[i])
    print sum(s)

lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
nested_sum(lists)

Please excuse the formatting.

Issue with this code lies in the line I have commented.

The error shown was:

NameError: global name 's' is not defined

How can I avoid this error without declaring the list s before?

Mark Skelton
  • 3,663
  • 4
  • 27
  • 47
Snake Eyes
  • 325
  • 5
  • 18

7 Answers7

3

If you delete the marked line you get a NameError because you try to index into something (s) before defining what that name should refer to. That should be clear.

The easiest way to solve your problem in one go is to us a generator expression in conjunction with sum with or without the chain function from itertools (depending on your preference).

Without chain:

>>> lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
>>> sum(value for sublist in lists for value in sublist)
56

With chain:

>>> from itertools import chain
>>> sum(chain(*lists))
56

which is equivalent to

>>> sum(chain.from_iterable(lists))
56
timgeb
  • 76,762
  • 20
  • 123
  • 145
2

You could convert your for loop to a oneliner so you don't have to pre-declare the variable s. Here is the code:

def nested_sum(lists):
    s = [sum(lists[i]) for i in range(len(lists))]  #converted for loop to oneliner
    print sum(s)

lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
nested_sum(lists)
Mark Skelton
  • 3,663
  • 4
  • 27
  • 47
1

In this case, you always have to declare list. But you can choose how. For example:

1) s = [0] * len(lists) - will be equal to your declaration

2) s = [], next you do something like this:

for i in range(len(lists)):
    s.append(sum(lists[i]))
Sergius
  • 908
  • 8
  • 20
  • 3
    But be careful when multiplying a list like that if there's mutable values in them, or the next question you will be asking is [this](http://stackoverflow.com/questions/240178/python-list-of-lists-changes-reflected-across-sublists-unexpectedly) one. ;) – timgeb Feb 29 '16 at 11:58
1

Specifically in your case you don't actually need s to achieve the same functionality (if you don't mind altering the contents of lists):

def nested_sum(lists):
    for i in range(len(lists)):
        lists[i] = sum(lists[i])
    print sum(lists)

>>> lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
>>> nested_sum(lists)
56
Idos
  • 15,053
  • 14
  • 60
  • 75
  • 1
    This will change the original list. Not sure OP wants to do this. – tobias_k Feb 29 '16 at 11:42
  • I have stated that clearly, if the OP isn't interested and let's me know I'll obviously delete/edit my answer accordingly :) – Idos Feb 29 '16 at 11:44
1

Another way to do this would be to use a variable to store the sum rather than a list and use the 'in' keyword to iterate through the list items rather than a range:

def nested_sum(lists):
    list_sum = 0
    for i in lists:
        list_sum += sum(i)
    print (list_sum)

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

nested_sum(lists)
Hassan.S
  • 69
  • 1
  • 1
  • 8
1

You don't need any intermediate list (and no extra memory, as per the comment by Lol4t0)

def nested_sum(lists):
    print sum(sum(l) for l in lists)

the syntax I've used is a generator expression.

Of course it is much more flexible to declare your function w/o the print,

def nested_sum(lists):
    return sum(sum(l) for l in lists)

and then use it like this

l = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
print nested_sum(l)
gboffi
  • 22,939
  • 8
  • 54
  • 85
0

There is a shorter and more pythonic way of doing that:

>>> lists = [[2,4], [1]]
>>> [sum(x) for x in lists]

output: [6, 1]

You can read further on list comprehensions