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

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

其他回答

如果你喜欢递归,这可能是你感兴趣的解决方案:

def f(E):
    if E==[]: 
        return []
    elif type(E) != list: 
        return [E]
    else:
        a = f(E[0])
        b = f(E[1:])
        a.extend(b)
        return a

实际上,这是从我以前写的一些Scheme代码中改编而来的。

享受吧!

@unutbu的非递归解决方案的生成器版本,由@Andrew在评论中要求:

def genflat(l, ltypes=collections.Sequence):
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        yield l[i]
        i += 1

这个生成器的简化版本:

def genflat(l, ltypes=collections.Sequence):
    l = list(l)
    while l:
        while l and isinstance(l[0], ltypes):
            l[0:1] = l[0]
        if l: yield l.pop(0)

python 3

from collections import Iterable

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

def flatten(thing):
    result = []

    if isinstance(thing, Iterable):
        for item in thing:
            result.extend(flatten(item))
    else:
        result.append(thing)

    return result


flat = flatten(L)
print(flat)

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

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

下面是2.7.5中的compiler.ast.flatten实现:

def flatten(seq):
    l = []
    for elt in seq:
        t = type(elt)
        if t is tuple or t is list:
            for elt2 in flatten(elt):
                l.append(elt2)
        else:
            l.append(elt)
    return l

有更好、更快的方法(如果你已经到达这里,你已经看到它们了)

还要注意:

2.6版后已移除:在Python 3中已移除编译器包。