I'd like to flatten lists that may contain other lists without breaking strings apart. For example:
In [39]: list( itertools.chain(*["cat", ["dog","bird"]]) )
Out[39]: ['c', 'a', 't', 'dog', 'bird']
and I would like
['cat', 'dog', 'bird']
I'd like to flatten lists that may contain other lists without breaking strings apart. For example:
In [39]: list( itertools.chain(*["cat", ["dog","bird"]]) )
Out[39]: ['c', 'a', 't', 'dog', 'bird']
and I would like
['cat', 'dog', 'bird']
 
    
    def flatten(foo):
    for x in foo:
        if hasattr(x, '__iter__') and not isinstance(x, str):
            for y in flatten(x):
                yield y
        else:
            yield x
def flatten(foo):
    for x in foo:
        if hasattr(x, '__iter__'):
            for y in flatten(x):
                yield y
        else:
            yield x
(In Python 2.x, strings conveniently didn't actually have an __iter__ attribute, unlike pretty much every other iterable object in Python. Note however that they do in Python 3, so the above code will only work in Python 2.x.)
A slight modification of orip's answer that avoids creating an intermediate list:
import itertools
items = ['cat',['dog','bird']]
itertools.chain.from_iterable(itertools.repeat(x,1) if isinstance(x,str) else x for x in items)
 
    
    a brute force way would be to wrap the string in its own list, then use itertools.chain
>>> l = ["cat", ["dog","bird"]]
>>> l2 = [([x] if isinstance(x,str) else x) for x in l]
>>> list(itertools.chain(*l2))
['cat', 'dog', 'bird']
 
    
    def squash(L):
    if L==[]:
        return []
    elif type(L[0]) == type(""):
        M = squash(L[1:])
        M.insert(0, L[0])
        return M
    elif type(L[0]) == type([]):
        M = squash(L[0])
        M.append(squash(L[1:]))
        return M
def flatten(L):
    return [i for i in squash(L) if i!= []]
>> flatten(["cat", ["dog","bird"]])
['cat', 'dog', 'bird']
Hope this helps
 
    
    Here's a one-liner approach:
[item for sublist in [[item] if type(item) is not list else item for item in list1] for item in sublist]
 
    
    With the reduce function from the functools library you can do it like this:
import functools
items = ['cat',['dog','bird']]
print(functools.reduce(lambda a, b: [a] + b, items))
 
    
    a lambda function approach that works for more than two levels of hierarchy
>>> items = ['cat',['dog','bird',['fish']]] 
>>> flatten = lambda y: [k for j in ([i] if not isinstance(i,list) else flatten(i) for i in y) for k in j]
>>> flatten(items)
['cat', 'dog', 'bird', 'fish']
