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

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

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


当前回答

完全hack,但我认为它会工作(取决于你的data_type)

flat_list = ast.literal_eval("[%s]"%re.sub("[\[\]]","",str(the_list)))

其他回答

我的解决方案:

import collections


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

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

从我之前的回答来看,这个函数使我能想到的大多数情况变得平坦。我相信这适用于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中保留一些默认类来进行调用 函数更简洁。

这是我用递归做的:

def flatten(x):
    if not any(isinstance(e, list) for e in x):
        return x
    while type(x[-1]) == int:
        x = [x[-1]] + [x[:-1]]
    return flatten(x = x + x.pop(-1))

甚至:

def flatten(x):
    if not any(isinstance(e, list) for e in x):
        return x
    return flatten(x = x + x.pop([isinstance(e, list) for e in x].index(1)))

使用生成器函数可以使示例更易于阅读并提高性能。

Python 2

使用2.6中添加的Iterable ABC:

from collections import Iterable

def flatten(xs):
    for x in xs:
        if isinstance(x, Iterable) and not isinstance(x, basestring):
            for item in flatten(x):
                yield item
        else:
            yield x

Python 3

在Python 3中,basestring不再是,但元组(str, bytes)具有相同的效果。此外,yield from操作符每次从生成器返回一个项。

from collections.abc import Iterable

def flatten(xs):
    for x in xs:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

我们也可以使用python的'type'函数。当迭代列表时,我们检查项是否为列表。如果不是,我们“追加”它,否则我们“扩展”它。这里是一个示例代码-

l=[1,2,[3,4],5,[6,7,8]]
x=[]
for i in l:
    if type(i) is list:
        x.extend(i)
    else:
        x.append(i)
print x

输出:

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

要了解更多关于append()和extend()的信息,请访问这个网站: https://docs.python.org/2/tutorial/datastructures.html