是的,我知道之前已經討論過這個主題( 在這裏 , 這裏 , 這裏 , 這裏 ),可是據我所知,除一個解決方案外,全部解決方案在這樣的列表上均失敗: 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)
這是最好的模型嗎? 我有事嗎 任何問題? 函數
使用遞歸和鴨子類型生成器(針對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]
嘗試建立一個能夠平化Python中不規則列表的函數頗有趣,可是固然這就是Python的目的(使編程變得有趣)。 如下生成器在某些警告方面工做得很好: spa
def flatten(iterable): try: for item in iterable: yield from flatten(item) except TypeError: yield iterable
它將扁平化您可能但願單獨保留的數據類型(例如bytearray
, bytes
和str
對象)。 此外,代碼還依賴於如下事實:從不可迭代的對象請求迭代器會引起TypeError
。 code
>>> 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 >>>
這裏的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中刪除。
這是一個簡單的函數,能夠平鋪任意深度的列表。 沒有遞歸,以免堆棧溢出。
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
個人解決方案:
import collections def flatten(x): if isinstance(x, collections.Iterable): return [a for i in x for a in flatten(i)] else: return [x]
更加簡潔,但幾乎相同。