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

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

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


当前回答

只需使用函数库: PIP安装功能

import funcy


funcy.flatten([[[[1, 1], 1], 2], 3]) # returns generator
funcy.lflatten([[[[1, 1], 1], 2], 3]) # returns list

其他回答

这个答案的一个更有效的版本是:https://stackoverflow.com/a/20495215/8887313

如果您可以控制列表的创建并愿意更改它,那么使用deque(而不是pop(0)和列表contatenation)会更有效。

import collections

def flatten_and_consume(nested_deque: collections.deque):
    while nested_deque:
        elt = nested_deque.popleft()

        elt_is_sublist = isinstance(elt, collections.deque)
        if elt_is_sublist:
            nested_deque.extendleft(reversed(elt))
        else:
            yield elt

不使用实例的简单函数

L = [[[1, 2, 3], [4, 5]], 6]
l1 = []
def FlattenList(List1):
    for i in range(len(List1)):
        if type(List1[i]) == type([]):
            FlattenList(List1[i])
        else:
            l1.append(List1[i])
    return l1


FlattenList(L)
[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]

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

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

from iteration_utilities import deepflatten
list(deepflatten(test))

尝试在Python中创建一个可以平化不规则列表的函数是很有趣的,但当然,这就是Python的目的(让编程变得有趣)。以下生成器工作得相当好,但有一些注意事项:

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

它将平摊您可能希望保留的数据类型(如bytearray、bytes和str对象)。此外,代码依赖于这样一个事实,即从非可迭代对象请求迭代器会引发TypeError。

>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> def flatten(iterable):
    try:
        for item in iterable:
            yield from flatten(item)
    except TypeError:
        yield iterable


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

编辑:

我不同意之前的实现。问题是你不能将非可迭代对象的东西平展。它令人困惑,给人错误的印象的论点。

>>> list(flatten(123))
[123]
>>>

下面的生成器与第一个生成器几乎相同,但不存在试图将不可迭代对象平展的问题。当给它一个不恰当的论证时,它就会失败。

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

使用提供的列表测试生成器可以正常工作。但是,当给它一个不可迭代对象时,新代码将引发TypeError。下面是新行为的示例。

>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>> list(flatten(123))
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    list(flatten(123))
  File "<pyshell#27>", line 2, in flatten
    for item in iterable:
TypeError: 'int' object is not iterable
>>>