2013-06-27 73 views
9

壓扁名單列表我試圖用壓平列表理解Python中的列表。我的名單有點像通過列表理解

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

只是在列表名單打印,則單個項目我寫了這個代碼

def flat(listoflist): 
    for item in listoflist: 
      if type(item) != list: 
        print item 
      else: 
        for num in item: 
          print num 
>>> flat(list1) 
1 
2 
3 
4 
5 
6 
7 
8 

然後我用同樣的邏輯來拉平通過列表理解我的列表我得到出現以下錯誤

list2 = [item if type(item) != list else num for num in item for item in list1] 
    Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    TypeError: 'int' object is not iterable 

如何使用列表理解來壓扁這種列表清單?

回答

6
>>> from collections import Iterable 
>>> from itertools import chain 

一行代碼:

>>> list(chain.from_iterable(item if isinstance(item,Iterable) and 
        not isinstance(item, basestring) else [item] for item in lis)) 
[1, 2, 3, 4, 5, 6, 7, 8] 

可讀版本:

>>> def func(x):           #use `str` in py3.x 
...  if isinstance(x, Iterable) and not isinstance(x, basestring): 
...   return x 
...  return [x] 
... 
>>> list(chain.from_iterable(func(x) for x in lis)) 
[1, 2, 3, 4, 5, 6, 7, 8] 
#works for strings as well 
>>> lis = [[1, 2, 3], [4, 5, 6], 7, 8, "foobar"] 
>>> list(chain.from_iterable(func(x) for x in lis))                 
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar'] 

使用嵌套列表理解:(去相比itertools.chain是緩慢):

>>> [ele for item in (func(x) for x in lis) for ele in item] 
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar'] 
+1

工作這是偉大的使用2.X提問者一個恥辱,但它是值得的3.x中用戶應該使用'str',而不是一個音符'basestring'。 –

+0

@Ashwini如果我的元素的類型是dict而不是整數,應該怎麼做? –

+0

@AnuragSharma小例子? –

3

你試圖通過一個號碼,你不能這樣做(因此錯誤)進行迭代。

如果你正在使用Python 2.7:

>>> from compiler.ast import flatten 
>>> flatten(l) 
[1, 2, 3, 4, 5, 6, 7, 8] 

但是千萬注意,模塊現在已經過時,並在Python 3不再存在

+1

類型檢查列表是一個壞主意。這使得這種靈活性更低。 –

+1

如果'l'是'[[1,2,3],[4,5,6,第7,888]',第一溶液的產量'[1,2,3,4,5,6,7, 8,8,8]'。 – falsetru

+0

刪除了第一位,但它是我的其他解決方案將不會在Python 3 – TerryA

3

另一種解決方案使用發電機:

import collections 

def flatten(iterable): 
    for item in iterable: 
     if isinstance(item, collections.Iterable) and not isinstance(item, str): # `basestring` < 3.x 
      yield from item # `for subitem in item: yield item` < 3.3 
     else: 
      yield item 

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

+1從不知道''語句產量「。 –

3

沒有人已經考慮到通常的答案:

def flat(l): 
    return [y for x in l for y in x] 

這個問題有一些關於浮動在StackOverflo W上。

+1

您的代碼不適用於OP提供的列表,因爲他的列表包含非可迭代對象,即整數。 但是,如果列表中的每個項目都是可迭代對象,那麼您的代碼確實可行。 看到我下面的評論。 – JDG

+1

謝謝你指出 - 我實際上需要找到一個時刻來解決這個問題,並抓緊時間...... – GreenAsJade