0

As an exercise, I'm creating a code which recursively sums the elements of a list, including lists within lists.

Sample list: a = [1,2,[3,4],[5,6]]

Sample result: 21

My code is as follows:

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

def sum(list):
    if len(list[0]) == 1 and len(list) ==1: # case where list is [x]
        return list[0]
    elif len(list[0]) == 1 and len(list) > 1: # case where list is [x, etc]
        return list[0] + sum(list[1:])
    elif len(list[0]) > 1 and len(list == 1): # case where list is [[x,etc]]
        return sum(list[0])
    else:                                     # case where list is [[x, etc], etc]
        return sum(list[0]) + sum(list[1:])

print (sum(a))

However, when I try to run this I get the error "object of type 'int' has no length." I was under the impression that list[0] would just have a length of 1 if it's not a list in itself, but obviously, that doesn't work. What should I be doing instead to check whether an element in a list is itself a list?

Chase
  • 61
  • 6
  • Do you want to check only for lists, or also for tuples, sets, dicts, other iterables that can contain numbers, or all iterables such as strings? For a general routine, you probably should recursively "go into" all iterables, sum all numbers, and ignore the rest. – Rory Daulton Mar 12 '17 at 01:36
  • In this particular case, the only valid elements would be either integer or [integers], so just lists. That being said, if there's a more general way to check, that would probably be better to know for expansion from the exercise. – Chase Mar 12 '17 at 01:38
  • To check for an iterable, [see here](http://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable). To check for a number, use `isinstance(x, numbers.Number)`. – Rory Daulton Mar 12 '17 at 01:42

3 Answers3

3

What should I be doing instead to check whether an element in a list is itself a list?

if isinstance(x, list):

Common Gotchas You shouldn't name your own variables as list because you then overwrite the type list and function list()

Similarly for your function sum(). You wouldn't want to overwrite the sum() function that already handles a list of numbers.


Or another way would be hasattr(lst, "__len__")

from numbers import Number

def recur_sum(lst):
  # Return single value immeadiately
  if not lst or lst is None:
    return 0
  if isinstance(lst, Number):
    return lst

  head = None 
  tail = False
  if hasattr(lst, "__len__"):
    _size = len(lst)
    if _size <= 0: # case where list is []
      head = 0
    elif _size >= 1:
      if hasattr(lst[0], "__len__"):  # case where list is [[x,etc]]
        head = recur_sum(lst[0]) 
      else: # case where list is [x]
        head = lst[0] 
    tail = (_size > 1)

  if not tail:
    return head 
  else: 
    return head + recur_sum(lst[1:])
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
2

In short, you may use the isinstance function to check if an element is a list or not.

The follwoing code may serve as an example.

a = [1,2,[3,4],[5,6]]
a
Out[3]: 
[1, 2, [3, 4], [5, 6]]
isinstance(a,list)
Out[4]: 
True
isinstance(a[0],list)
Out[5]: 
False
isinstance(a[2],list)
Out[6]: 
True
Ray Z
  • 21
  • 2
0

For an item in the list you may change the if condition to if type(item) is list:

a = [1,2,[3,4],[5,6]]
for item in a:
    if type(item) is list:
        # do_something_with(item)
        print(item)

and the output will look like this:

[3,4]
[5,6]

Make sure the reserved word list is not overwritten as a variable!

Reza Dodge
  • 174
  • 1
  • 2
  • 4