2013-10-21 18 views
22

剛開始使用Python周圍玩弄所以請多多包涵:)Python的 - 提取內大多數列表

假設下面的列表中包含嵌套列表:

[[[[[1, 3, 4, 5]], [1, 3, 8]], [[1, 7, 8]]], [[[6, 7, 8]]], [9]] 

在不同的表示:

[ 
    [ 
     [ 
      [ 
       [1, 3, 4, 5] 
      ], 
      [1, 3, 8] 
     ], 
     [ 
      [1, 7, 8] 
     ] 
    ], 
    [ 
     [ 
      [6, 7, 8] 
     ] 
    ], 
    [9] 
] 

你將如何去提取這些內部列表,以便返回以下形式的結果:

[[1, 3, 4, 5], [1, 3, 8], [1, 7, 8], [6, 7, 8], [9]] 

非常感謝!

EDIT(感謝@falsetru):

空的內部列表或混合類型列表永遠不會是輸入的一部分。

+2

什麼,應該返回'[[[[[1,3,4,5],[1,3,8] ,[[1,7,8]],[[[6,7,8]],[9,[10]]]和'[[[[1,3,4,5]], [1,3,8]],[[1,7,8]],[[[6,7,8]]],[]]'? – falsetru

+0

感謝您的澄清問題: 一個空的列表或混合類型的項目將永遠不會成爲輸入的一部分 –

回答

32

這似乎是工作,假設沒有 '混合' 名單像[1,2,[3]]

輸出 list(get_inner(nested_list))
def get_inner(nested): 
    if all(type(x) == list for x in nested): 
     for x in nested: 
      for y in get_inner(x): 
       yield y 
    else: 
     yield nested 

[[1, 3, 4, 5], [1, 3, 8], [1, 7, 8], [6, 7, 8], [9]] 

或者更短,無需生成,使用sum所得到的列表合併:

def get_inner(nested): 
    if all(type(x) == list for x in nested): 
     return sum(map(get_inner, nested), []) 
    return [nested] 
+0

美麗!謝謝:) –

13

使用itertools.chain.from_iterable

from itertools import chain 

def get_inner_lists(xs): 
    if isinstance(xs[0], list): # OR all(isinstance(x, list) for x in xs) 
     return chain.from_iterable(map(get_inner_lists, xs)) 
    return xs, 

使用isinstance(xs[0], list)代替all(isinstance(x, list) for x in xs),因爲沒有混合列表/空的內部列表。


>>> list(get_inner_lists([[[[[1, 3, 4, 5]], [1, 3, 8]], [[1, 7, 8]]], [[[6, 7, 8]]], [9]])) 
[[1, 3, 4, 5], [1, 3, 8], [1, 7, 8], [6, 7, 8], [9]] 
5

比遞歸效率更高:

result = [] 
while lst: 
    l = lst.pop(0) 
    if type(l[0]) == list: 
     lst += [sublst for sublst in l if sublst] # skip empty lists [] 
    else: 
     result.insert(0, l) 
+3

從列表中刪除第一個項目,插入到列表的開頭需要O(n)時間。使用['collections.deque'](http://docs.python.org/2/library/collections.html#collections.deque)可以提高速度。請參閱http://ideone.com/RFGhnh – falsetru

+1

如果您聲稱您的解決方案比其他解決方案更高效,請附上小型和大型輸入的基準。請參閱falsetru的評論爲什麼它很慢。 – pts