是的,我知道这个主题之前已经被讨论过了:

Python成语链(扁平化)有限迭代对象的无限迭代? 在Python中扁平化一个浅列表 理解平展一个序列的序列吗? 我如何从列表的列表中创建一个平面列表?

但据我所知,所有的解决方案,除了一个,在像[[[1,2,3],[4,5]],6]这样的列表上失败,其中期望的输出是[1,2,3,4,5,6](或者更好,一个迭代器)。

我看到的唯一解决方案,适用于任意嵌套是在这个问题:

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__") and not isinstance(el, basestring):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

这是最好的方法吗?我是不是忽略了什么?任何问题吗?


当前回答

没有递归或嵌套循环。几行。格式良好,易于阅读:

def flatten_deep(arr: list):
    """ Flattens arbitrarily-nested list `arr` into single-dimensional. """

    while arr:
        if isinstance(arr[0], list):  # Checks whether first element is a list
            arr = arr[0] + arr[1:]  # If so, flattens that first element one level
        else:
            yield arr.pop(0)  # Otherwise yield as part of the flat array

flatten_deep(L)

从我自己的代码https://github.com/jorgeorpinel/flatten_nested_lists/blob/master/flatten.py

其他回答

我是一个愚蠢的人,所以我会给出一个“愚蠢”的解决方案。所有的递归都伤了我的大脑。

flattened_list = []
nested_list = [[[1, 2, 3], [4, 5]], 6]

def flatten(nested_list, container):
    for item in nested_list:
        if isintance(item, list):
            flatten(item, container)
        else:
            container.append(item)

>>> flatten(nested_list, flattened_list)
>>> flattened_list
[1, 2, 3, 4, 5, 6]

我知道这是一个副作用但这是我对递归的最好理解

我是python的新手,有lisp的背景。这是我想出的(检查lulz的var名称):

def flatten(lst):
    if lst:
        car,*cdr=lst
        if isinstance(car,(list,tuple)):
            if cdr: return flatten(car) + flatten(cdr)
            return flatten(car)
        if cdr: return [car] + flatten(cdr)
        return [car]

似乎有用。测试:

flatten((1,2,3,(4,5,6,(7,8,(((1,2)))))))

返回:

[1, 2, 3, 4, 5, 6, 7, 8, 1, 2]

从我之前的回答来看,这个函数使我能想到的大多数情况变得平坦。我相信这适用于python 2.3。

def flatten(item, keepcls=(), keepobj=()):
    if not hasattr(item, '__iter__') or isinstance(item, keepcls) or item in keepobj:
        yield item
    else:
        for i in item:
            for j in flatten(i, keepcls, keepobj + (item,)):
                yield j

循环链表

>>> list(flatten([1, 2, [...], 3]))
[1, 2, [1, 2, [...], 3], 3]

深度优先列表

>>> list(flatten([[[1, 2, 3], [4, 5]], 6]))
[1, 2, 3, 4, 5, 6]

嵌套重复列表:

>>> list(flatten([[1,2],[1,[1,2]],[1,2]]))
[1, 2, 1, 1, 2, 1, 2]

带有字典的列表(或其他不要压平的对象)

>>> list(flatten([1,2, {'a':1, 'b':2}, 'text'], keepcls=(dict, str)))
[1, 2, {'a': 1, 'b': 2}, 'text']

任何iterable

>>> list(flatten((x for x in [1,2, set([3,(4,5),6])])))
[1, 2, 4, 5, 3, 6]

您可能希望在keepcls中保留一些默认类来进行调用 函数更简洁。

L2 = [o for k in [[j] if not isinstance(j,list) else j for j in [k for i in [[m] if not 
isinstance(m,list) else m for m in L] for k in i]] for o in k]
def flatten(item) -> list:
    if not isinstance(item, list): return item
    return reduce(lambda x, y: x + [y] if not isinstance(y, list) else x + [*flatten(y)], item, [])

双行递减函数。