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

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

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


当前回答

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

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]

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

其他回答

我的解决方案:

import collections


def flatten(x):
    if isinstance(x, collections.Iterable):
        return [a for i in x for a in flatten(i)]
    else:
        return [x]

更简洁一点,但基本相同。

我试过不使用任何库来解决它。只需使用两个嵌套函数即可。

def first(list_to_flatten):
    a = []

    def second(list_to_flatten):
        for i in list_to_flatten:
            if type(i) is not list:
                a.append(i)
            else:
                list_to_flatten = i
                second(list_to_flatten)

    second(list_to_flatten)
    return a

list_to_flatten = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]
a = first(list_to_flatten)
print(a)

>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

该解决方案基于python的迭代实用程序库及其函数deepflatten

from iteration_utilities import deepflatten
list(deepflatten(test))

使用递归和duck类型的生成器(为Python 3更新):

def flatten(L):
    for item in L:
        try:
            yield from flatten(item)
        except TypeError:
            yield item

list(flatten([[[1, 2, 3], [4, 5]], 6]))
>>>[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]