简体   繁体   中英

Python converting a tuple (of strings) of unknown length into a list of strings

I have a recursive tuple of strings that looks like this:

('text', ('othertext', ('moretext', ('yetmoretext'))))

(it's actually a tuple of tuples of strings - it's constructed recursively)

And I'd like to flatten it into a list of strings, whereby foo[1] would contain "text", foo[2] "othertext" and so forth.

How do I do this in Python?

The duplicate is about a 2D list of lists, but here I'm dealing with a recursive tuple.

I've found the answer myself, I'll provide it here for future reference:

stringvar = []
while type(tuplevar) is tuple:
        stringvar.append(tuplevar[0])
        tuplevar=tuplevar[1]
stringvar.append(tuplevar)  # to get the last element. 

Might not be the cleanest/shortest/most elegant solution, but it works and it seems quite "Pythonic".

If you're happy that the level of recursion isn't going to get horrible (and you're using an up to date version of Python):

def unpack(obj):
    for x in obj:
        if isinstance(x, str):
            yield x
        elif isinstance(x, tuple):
            yield from unpack(x)
        else:
            raise TypeError

x = ('text', ('othertext', ('moretext', ('yetmoretext',))))
result = list(unpack(x))
print(result)

Will give you:

['text', 'othertext', 'moretext', 'yetmoretext']

This will also work if there are more than 1 strings before the next tuple, or if there are tuples directly in tuples, or strings after tuples etc. You can also easily modify it to work with other types if you need, I've probably unnecessarily erred on the side of caution.

This is how I would approach it. This is very similar to a previous answer, however it's more general in application, as it allows any type of iterable to be flattened, except for string-type objects (ie, lists and tuples), and it also allows for the flattening of lists of non-string objects.

# Python 3.
from collections import abc

def flatten(obj):
    for o in obj:
        # Flatten any iterable class except for strings.
        if isinstance(o, abc.Iterable) and not isinstance(o, str):
            yield from flatten(o)
        else:
            yield o

data = ('a', ('b', 'c'), [1, 2, (3, 4.0)], 'd')
result = list(flatten(data))
assert result == ['a', 'b', 'c', 1, 2, 3, 4.0, 'd']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM