-1

A link to the original question: Nested List and count()

I was testing the accepted answer's code and found it to not work for list that contain strings.

The accepted answer's code:

def flatten(seq,container=None):
    if container is None:
        container = []
    for s in seq:
        if hasattr(s,'__iter__'):
            flatten(s,container)
        else:
            container.append(s)
    return container

c = flatten([(1,2),(3,4),(5,[6,7,['a','b']]),['c','d',('e',['f','g','h'])]])
print c
print c.count('g')

d = flatten([[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]])
print d
print d.count(1)

I tested using this input at first:

list1 = [[[1,2,3,4,5],[1,2,3,4,5]],[[1,2,3,4,5],[1,2,3,4,5]],[[1,2,3,4,5],[1,2,3,4,5]]]

And it worked.

But once I use this:

list1 = [[[1,'2',3,4,5],[1,2,3,4,5]],[[1,2,3,4,5],[1,2,3,4,5]],[[1,2,3,4,5],[1,2,3,4,5]]]

Note: The first 2 is now a string.

It produces this error:

RecursionError: maximum recursion depth exceeded

I understand recursion, but I don't why this error happens. Initially, I thought it has something to do with '__iter__' but I'm pretty sure strings are iterable because I've checked.

For reference, I'm using Python 3.6.4.

And I'm still new to Python, please be nice to me :)

Irfan Zainudin
  • 55
  • 4
  • 11

1 Answers1

2

Strings are a problem for that flatten function because they're iterable, but when you iterate inside a string, you always get another string. Even a one character string remains iterable, and yields a copy of itself (another one character string).

So you need to change your check for whether you should recurse or not. Rather than recursing any time you find an iterable object, you need to specifically exclude strings:

if hasattr(s,'__iter__') and not isinstance(s, str):
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Worth mentioning: the original answer is specific to Python 2, and in Python 2.x, `hasattr(stringobj, '__iter__')` returns `False`. – torek Sep 11 '18 at 00:33