Подтвердить что ты не робот

Как можно сгладить списки без разделения строк?

Я хотел бы сгладить списки, которые могут содержать другие списки, не разбивая строк. Например:

In [39]: list( itertools.chain(*["cat", ["dog","bird"]]) )
Out[39]: ['c', 'a', 't', 'dog', 'bird']

и я хотел бы

['cat', 'dog', 'bird']
4b9b3361

Ответ 1

def flatten(foo):
    for x in foo:
        if hasattr(x, '__iter__'):
            for y in flatten(x):
                yield y
        else:
            yield x

(У строк обычно нет атрибута __iter__, в отличие от почти любого другого итерабельного объекта в Python. Обратите внимание, что это изменяется в Python 3, поэтому приведенный выше код будет работать только в Python 2.x.)

Версия для Python 3.x:

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

Ответ 2

Небольшая модификация ответа orip, которая позволяет избежать создания промежуточного списка:

import itertools
items = ['cat',['dog','bird']]
itertools.chain.from_iterable(itertools.repeat(x,1) if isinstance(x,str) else x for x in items)

Ответ 3

способ грубой силы - обернуть строку в свой собственный список, а затем использовать 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']

Ответ 4

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']

Надеюсь, что это поможет