拼合不規則的列表

是的,我知道之前已經討論過這個主題( 在這裏這裏這裏這裏 ),可是據我所知,除一個解決方案外,全部解決方案在這樣的列表上均失敗: shell

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

所需的輸出是 編程

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

甚至更好的迭代器。 這個問題是我看到的惟一適用於任意嵌套的解決方案: app

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

flatten(L)

這是最好的模型嗎? 我有事嗎 任何問題? 函數


#1樓

使用遞歸和鴨子類型生成器(針對Python 3更新): 測試

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

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

#2樓

嘗試建立一個能夠平化Python中不規則列表的函數頗有趣,可是固然這就是Python的目的(使編程變得有趣)。 如下生成器在某些警告方面工做得很好: spa

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

它將扁平化您可能但願單獨保留的數據類型(例如bytearraybytesstr對象)。 此外,代碼還依賴於如下事實:從不可迭代的對象請求迭代器會引起TypeErrorcode

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

如下生成器與第一個生成器幾乎相同,可是不存在試圖展平不可迭代對象的問題。 當給它一個不適當的參數時,它會像人們指望的那樣失敗。 get

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

#3樓

這裏的compiler.ast.flatten在2.7.5的實現:

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中刪除。


#4樓

這是一個簡單的函數,能夠平鋪任意深度的列表。 沒有遞歸,以免堆棧溢出。

from copy import deepcopy

def flatten_list(nested_list):
    """Flatten an arbitrarily nested list, without recursion (to avoid
    stack overflows). Returns a new list, the original list is unchanged.

    >> list(flatten_list([1, 2, 3, [4], [], [[[[[[[[[5]]]]]]]]]]))
    [1, 2, 3, 4, 5]
    >> list(flatten_list([[1, 2], 3]))
    [1, 2, 3]

    """
    nested_list = deepcopy(nested_list)

    while nested_list:
        sublist = nested_list.pop(0)

        if isinstance(sublist, list):
            nested_list = sublist + nested_list
        else:
            yield sublist

#5樓

個人解決方案:

import collections


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

更加簡潔,但幾乎相同。

相關文章
相關標籤/搜索