6

This will capitalize them but only if there are no nested lists.

t = ['this','that', ['other']]

def capitalize_nested(t):
    res = []
    for s in t:
        res.append(s.capitalize())
    return res

print capitalize_nested(t)

I can't figure out how to get it to print out a nested list having all of the strings start with a capital letter. I must be missing something obvious, this just has me stumped.

5 Answers5

12

Use a recursive solution (and using list comprehensions also helps make it more compact):

def capitalize_nested(t):
    if isinstance(t, list):
        return [capitalize_nested(s) for s in t]
    else:
        return t.capitalize()

For example:

print capitalize_nested(['this', 'that', ['other']])
# ['This', 'That', ['Other']]
David Robinson
  • 77,383
  • 16
  • 167
  • 187
  • @Amber: good idea, changed (though the question does ask just for nested lists). – David Robinson Dec 24 '12 at 18:01
  • @Amber: Actually I just realized I can't do that at all, because `isinstance("this", collections.Sequence)` (calling on a string) returns True, so it will recurse infinitely on each of the strings. – David Robinson Dec 24 '12 at 18:04
  • True. Perhaps it would be safer to see if the thing in question is *not* a string. – Amber Dec 24 '12 at 18:06
3
def cap(L):
    for i,elem in enumerate(L):
         if isinstance(elem, str):
             L[i] = elem.capitalize()
         elif isinstance(elem, list):
             cap(L[i])
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
2

Just check if s is a list then recursively call your capitalize_nested function:

t = ['this','that', ['other']]

def capitalize_nested(t):
    res = []
    for s in t:
        if type(s) == list:
            res.append(capitalize_nested(s))
        else:
            res.append(s.capitalize())
    return res

print capitalize_nested(t)
NominSim
  • 8,447
  • 3
  • 28
  • 38
1

The recursive solution is first solution and most beautiful solution, but not always the best solution, Check this iterative solution too:

def capitalize(t):
    lists = [t]
    while lists:
        l = lists.pop()
        for i, item in enumerate(l):
            if isinstance(item, list):
                lists.append(item)
            else:
                l[i] = item.capitalize()
MostafaR
  • 3,547
  • 1
  • 17
  • 24
  • You are using `lists` as a stack by appending to it while iterating over it. I'm not sure whether such semantics is guaranteed by Python language but it works on Python 2.x, 3.x, Pypy, Jython. I've used explicit `while stack: lst = stack.pop()` in [the similar solution](http://stackoverflow.com/a/14024633/4279). – jfs Dec 24 '12 at 18:42
  • @J.F.Sebastian Thank you for your hint, I just improved the code. – MostafaR Dec 24 '12 at 18:45
1

Here's a version that supports an arbitrary deep nested list:

from collections import MutableSequence

def capitalize_inplace(nested_list):
    stack = [nested_list]
    while stack:
        lst = stack.pop()
        for i, item in enumerate(lst):
            if isinstance(item, MutableSequence):
                stack.append(item)
            else:
                lst[i] = item.capitalize()

Example

L = ['this', 'that', ['other'], ['may',['be', ['nested'], 'further']]]
capitalize_inplace(L)
print(L)
# -> ['This', 'That', ['Other'], ['May', ['Be', ['Nested'], 'Further']]]
jfs
  • 399,953
  • 195
  • 994
  • 1,670