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

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

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


当前回答

我很惊讶居然没人想到这一点。该死的递归,我没有得到这里的高级人员给出的递归答案。总之,这是我的尝试。警告是它非常特定于OP的用例

import re

L = [[[1, 2, 3], [4, 5]], 6]
flattened_list = re.sub("[\[\]]", "", str(L)).replace(" ", "").split(",")
new_list = list(map(int, flattened_list))
print(new_list)

输出:

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

其他回答

L2 = [o for k in [[j] if not isinstance(j,list) else j for j in [k for i in [[m] if not 
isinstance(m,list) else m for m in L] for k in i]] for o in k]

虽然已经选择了一个优雅和非常python的答案,但我将提出我的解决方案,只是为了回顾:

def flat(l):
    ret = []
    for i in l:
        if isinstance(i, list) or isinstance(i, tuple):
            ret.extend(flat(i))
        else:
            ret.append(i)
    return ret

请告诉我这个代码是好是坏?

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

from iteration_utilities import deepflatten
list(deepflatten(test))

我修改了接受的答案的代码,并添加了关键字max_depth,以只将其压平到指定的深度。Max_depth =0表示列表保持原样。也许有人可以用它:

def flatten(l, __depth=0, max_depth=100):

    for el in l:

        if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)):

            __depth += 1
            if __depth <= max_depth:
                yield from flatten(el, __depth=__depth, max_depth=max_depth)
            else:
                yield el
            __depth -= 1

        else:

            yield el

一些例子:

# A
l = []
depth = 5
for i in range(depth):
    el = i
    for j in range(i):
        el = [el]
    l.append(el)
# [0, [1], [[2]], [[[3]]], [[[[4]]]]]

for i in range(depth):
    print(list(flatten_gen(l, max_depth=i)))
# [0, [1], [[2]], [[[3]]], [[[[4]]]]]
# [0,  1,   [2],   [[3]],   [[[4]]]]
# [0,  1,    2,     [3],     [[4]]]
# [0,  1,    2,      3,       [4]]
# [0,  1,    2,      3,        4]


# B
l = [[1, 2], [3, 4, [5, 6, [7, [8, [9]]], 10], 12, [13]], 14, [15]]

for i in range(6):
    print(list(flatten_gen(l, max_depth=i)))
# [[1, 2], [3, 4, [5, 6, [7, [8, [9]]], 10], 12, [13]], 14, [15]]
# [ 1, 2,   3, 4, [5, 6, [7, [8, [9]]], 10], 12, [13],  14,  15]
# [ 1, 2,   3, 4,  5, 6, [7, [8, [9]]], 10,  12,  13,   14,  15]
# [ 1, 2,   3, 4,  5, 6,  7, [8, [9]],  10,  12,  13,   14,  15]
# [ 1, 2,   3, 4,  5, 6,  7,  8, [9],   10,  12,  13,   14,  15]
# [ 1, 2,   3, 4,  5, 6,  7,  8,  9,    10,  12,  13,   14,  15]

这是我的递归flatten的函数版本,它可以处理元组和列表,并允许您抛出任何位置参数的混合。返回一个生成器,它会逐参数依次生成整个序列:

flatten = lambda *n: (e for a in n
    for e in (flatten(*a) if isinstance(a, (tuple, list)) else (a,)))

用法:

l1 = ['a', ['b', ('c', 'd')]]
l2 = [0, 1, (2, 3), [[4, 5, (6, 7, (8,), [9]), 10]], (11,)]
print list(flatten(l1, -2, -1, l2))
['a', 'b', 'c', 'd', -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]