Iterate through lists of lists and single elements

Viewed 143

Given the following list,

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

I want to go through all its elements. As you see when the subset has only one element I do not have a list of 1 but just the element alone. So of course this does not work because the second element of a is not iterable,

for x in a:
    for i in x:
        print(i)
        #do much more

Error:

   for i in x:

TypeError: 'int' object is not iterable

I can do the following, but I find it very unhandy, because I have to copy code, or call a function in the part '#do much more. Any idea?

for x in a:
    if type(x) is list:
        for i in x:
            print(i)
            #do much more
    else:
        print(x)
        #do much more (the same as above)
4 Answers

The problem is that you have a set where each element could be a set or a single element. If you want to avoid flattening, and the flattened output from @green-cloak-guy doesn't suite your usage, you can instead curate the data prior to consuming, so that you can consume it as a guaranteed list of lists.

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

for x in a:
    if not isinstance(x, list):
        x = [x]
    for i in x:
        print(i)
        #do much more

I know no python, seriously, but that should do it for you.

p.s. Seriously, I don't know python. You just pick things up, and I ran that in a REPL to verify it.

A "pythonic" way to do it that doesn't require type-checking and avoids having to repeating yourself would be to use what's called the EAFP ("It's easier to ask forgiveness than permission") style of coding (see my answer to another question for more details).

Here's how to apply it to this scenario:

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

for x in a:
    try:
        it = iter(x)
    except TypeError:
        it = [x]
    for i in it:
        print(i)
        #do much more

Write a recursive function to do it for you:

def print_my_list(lst):
    for elem in lst:
        if type(elem) is list:
            print_my_list(elem)
        else:
            print(elem)

One nice thing is that this will work for any number of lists nested within each other, 'flattening' them all.

You can move your additional logic out of the loop by defining a function that returns a generator:

def flatten(items):
    for item in items:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

a = [[1,2,3],1,[1,2,43,5],[1,23,4,4],6.5,[1,1,2,45]]

for i in flatten(a):
    print(i)
    # Your logic here!

You can verify the output of the code above:

1
2
3
1
1
2
43
5
1
23
4
4
6.5
1
1
2
45
Related