I need to write a loop that traverses the list and prints the length of each element. So far I have this:

def countEachElement():
	elements= ["spam!",'1',['Brie','Roquefort','Pol le Veq'],['1','2','3']]
	i=0
	while i < len(elements):
		print len(elements[i])
		i=i+1

But it's not counting each element of the lists inside the list. What should I do?

Dani AI

Generated

The original loop calls len() on each top-level item, so a sublist yields its item count (e.g. 3), not the lengths of the strings inside it. There are two common goals here: (A) print a length for every atomic element found inside nested lists (strings, numbers, etc.), or (B) produce a parallel nested structure where each original element is replaced by its length. Which you need changes the approach.

Recursion or an explicit stack is the usual fix. Treat str (and bytes) as atomic even though they are iterable, and treat other non-iterables (numbers, None, custom objects) the way you prefer — many people convert them to str and use len(str(x)). As noted, recursion is a natural fit; correctly pointed out converting non-iterables to strings is a pragmatic choice; and reminded to be careful when testing for sequence-ness. A robust check is to use collections.abc.Iterable while special-casing str/bytes.

A small, reusable pattern: write a function that (optionally) preserves nesting or flattens results, special-cases strings, and returns lengths rather than printing directly. This keeps logic testable and lets you print or collect later.

from collections.abc import Iterable

def lengths(obj, *, flatten=False):
    if isinstance(obj, (str, bytes)):
        return len(obj)
    if isinstance(obj, Iterable):
        items = [lengths(x, flatten=flatten) for x in obj]
        if flatten:
            flat = []
            for v in items:
                flat.extend(v if isinstance(v, list) else [v])
            return flat
        return items
    return len(str(obj))

Notes: import Iterable from collections on older Python versions if needed. If nesting can be very deep, use an explicit stack to avoid hitting the recursion limit. If you only want to print as you go, traverse the same structure but call print() on each atomic length instead of returning values.

Recommended Answers

All 3 Replies

You can use a recursive auxiliary function to count an element

def count(element):
    if isinstance(element, str):
        return len(element)
    else:
        return sum(count(x) for x in element)

def countEachElement():
    elements= ["spam!",'1',['Brie','Roquefort','Pol le Veq'],['1','2','3']]
    return count(elements)

print(countEachElement())

""" my output -->
32
"""

Remarks:
1) PLEASE, configure your editor to insert 4 spaces when you hit the tab key instead of a tab character.
2) It's Pont Leveque and not Pol le veq :)

In the same vein, here is some more fun

def concat(element):
    if isinstance(element, str):
        return element
    else:
        return "".join(concat(x) for x in element)
    
def recursionFun():
    elements= ["spam!",'1',['Brie','Roquefort','Pol le Veq'],['1','2','3']]
    result = concat(elements)
    print result
    print len(result)
    
recursionFun()

""" my output -->
spam!1BrieRoquefortPol le Veq123
32
"""

Perhaps this is not exactly what you want ? What do you expect as output ?

Maybe the poster liked to have list containing integer length instead of the element for every element of the list. Then for line 5 use statement to return list of counts.

What happens or is supposed to happen if the elements are numbers? Maybe len(str(element)) is better to add to if the case of element not having __iter___, not only strings.

def count(element):
    if isinstance(element, str) or not hasattr(element,'__iter__'):
        return len(str(element))
    else:
        return [count(x) for x in element]

def countEachElement():
    elements= ["spam!",1,['Brie','Roquefort','Pol le Veq'],['1',2.123,'3']]
    return count(elements)

print(countEachElement())

""" my output -->
[5, 1, [4, 9, 10], [1, 5, 1]]
"""

But remember that purpose of Life, Universe and Everything is 42 ;)!

Maybe the poster liked to have list containing integer length instead of the element for every element of the list. Then for line 5 use statement to return list of counts.

What happens or is supposed to happen if the elements are numbers? Maybe len(str(element)) is better to add to if the case of element not having __iter___, not only strings.

def count(element):
    if isinstance(element, str) or not hasattr(element,'__iter__'):
        return len(str(element))
    else:
        return [count(x) for x in element]

def countEachElement():
    elements= ["spam!",1,['Brie','Roquefort','Pol le Veq'],['1',2.123,'3']]
    return count(elements)

print(countEachElement())

""" my output -->
[5, 1, [4, 9, 10], [1, 5, 1]]
"""

But remember that purpose of Life, Universe and Everything is 42 ;)!

You may want to check hasattr(element, '__len__') instead.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.