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

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

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


当前回答

使用itertools.chain:

import itertools
from collections import Iterable

def list_flatten(lst):
    flat_lst = []
    for item in itertools.chain(lst):
        if isinstance(item, Iterable):
            item = list_flatten(item)
            flat_lst.extend(item)
        else:
            flat_lst.append(item)
    return flat_lst

或没有锁链的:

def flatten(q, final):
    if not q:
        return
    if isinstance(q, list):
        if not isinstance(q[0], list):
            final.append(q[0])
        else:
            flatten(q[0], final)
        flatten(q[1:], final)
    else:
        final.append(q)

其他回答

我知道已经有很多很棒的答案,但我想添加一个答案,使用函数式编程方法来解决这个问题。在这个答案中,我使用了双重递归:

def flatten_list(seq):
    if not seq:
        return []
    elif isinstance(seq[0],list):
        return (flatten_list(seq[0])+flatten_list(seq[1:]))
    else:
        return [seq[0]]+flatten_list(seq[1:])

print(flatten_list([1,2,[3,[4],5],[6,7]]))

输出:

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

这是我用递归做的:

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)))

我的解决方案:

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的迭代实用程序库及其函数deepflatten

from iteration_utilities import deepflatten
list(deepflatten(test))

用Python 3迭代解决

此解决方案可用于除str和bytes以外的所有对象。

from collections import Iterable
from collections import Iterator


def flat_iter(obj):
    stack = [obj]
    while stack:
        element = stack.pop()
        if element and isinstance(element, Iterator):
            stack.append(element)
            try:
                stack.append(next(element))
            except StopIteration:
                stack.pop()
        elif isinstance(element, Iterable) and not isinstance(element, (str, bytes)):
            stack.append(iter(element))
        else:
            yield element


tree_list = [[(1,2,3),(4,5,6, (7,8, 'next element is 5')), (5,6), [[[3,4,5],'foo1'],'foo2'],'foo3']]

not_iterable = 10

it1 = flat_iter(tree_list)
it2 = flat_iter(not_iterable)

print(list(it1))
print(list(it2))

[1, 2, 3, 4, 5, 6, 7, 8,下一个元素是5,5,6,3,4,5,‘foo1’,‘foo2’,‘foo3’) [10]