2013-02-11 55 views
2

我想收集所有的頭文件在一個子目錄列表。但是,如果我做混淆鏈式枚舉

from glob import glob 
from itertools import chain 

subDirs = ['FreeRTOS', 'Twig'] 
for each in chain(glob(eachDir+'/*.h') for eachDir in subDirs): 
    print each 

我得到的是

['FreeRTOS/croutine.h', 'FreeRTOS/FreeRTOS.h', 'FreeRTOS/FreeRTOSConfig.h', 'FreeRTOS/list.h', 'FreeRTOS/mpu_wrappers.h', 'FreeRTOS/portable.h', 'FreeRTOS/portmacro.h', 'FreeRTOS/projdefs.h', 'FreeRTOS/queue.h', 'FreeRTOS/semphr.h', 'FreeRTOS/StackMacros.h', 'FreeRTOS/task.h', 'FreeRTOS/timers.h'] 
['Twig/twig.h'] 

但我想看到的是

'FreeRTOS/croutine.h' 
'FreeRTOS/FreeRTOS.h' 
'FreeRTOS/FreeRTOSConfig.h' 
'FreeRTOS/list.h' 
'FreeRTOS/mpu_wrappers.h' 
'FreeRTOS/portable.h' 
'FreeRTOS/portmacro.h' 
'FreeRTOS/projdefs.h' 
'FreeRTOS/queue.h' 
'FreeRTOS/semphr.h' 
'FreeRTOS/StackMacros.h' 
'FreeRTOS/task.h' 
'FreeRTOS/timers.h' 
'Twig/twig.h' 

我認爲這就是鏈()會爲我做。我錯過了什麼?

回答

3

我認爲你正在尋找itertools.chain.from_iterable

import os 
import glob 
import itertools 

for each in itertools.chain.from_iterable(
     glob.glob(os.path.join(eachDir,'/*.h')) 
     for eachDir in subDirs): 
    print each 

它變平iterables的迭代:

In [6]: import itertools as IT 
In [7]: list(IT.chain.from_iterable([['a', 'b', 'c'], [1, 2, 3]])) 
Out[7]: ['a', 'b', 'c', 1, 2, 3] 
0

可能慢於unutbu的答案,但是這也將工作:

import collections 
def flattenIter(l): 
    """ 
     Iterator that flattens a list by one each iteration 
     To get a fully flattened list of L do: 
      list(flattenIter(L)) 
    """ 
    for el in l: 
     if isinstance(el, collections.Iterable) and not isinstance(el, basestring): 
      for sub in flattenIter(el): 
       yield sub 
     else: 
      yield el 

請注意,與unutbu的答案相比,這可以將列表中的任何數量的列表與他的方法相對比。例子:

print list(IT.chain.from_iterable([['a', 'b', 'c'], [1, 2, 3],"aap",["beer",[1]]])) 
# ['a', 'b', 'c', 1, 2, 3, 'a', 'a', 'p', 'beer', [1]] 
print list(flattenIter([['a', 'b', 'c'], [1, 2, 3],1,"aap",["beer",[1]]])) 
# ['a', 'b', 'c', 1, 2, 3, 1, 'aap', 'beer', 1] 

相同的 '出' 作爲unutbu的答案。

In : list(flattenIter([['a', 'b', 'c'], [1, 2, 3]])) 
Out: ['a', 'b', 'c', 1, 2, 3] 

這裏是unutbu的版本速度對比:

import timeit 
import collections 
import time 
import itertools as IT 

class Timer: 
    def __enter__(self): 
     self.start = time.clock() 
     return self 

    def __exit__(self, *args): 
     self.end = time.clock() 
     self.interval = self.end - self.start 

def flattenIter(l): 
    """ 
     Iterator that flattens a list by one each iteration 
     To get a fully flattened list of L do: 
      list(flattenIter(L)) 
    """ 
    for el in l: 
     if isinstance(el, collections.Iterable) and not isinstance(el, basestring): 
      for sub in flattenIter(el): 
       yield sub 
     else: 
      yield el 

with Timer() as t: 
    for x in xrange(10000): 
     list(IT.chain.from_iterable([['a', 'b', 'c'], [1, 2, 3]])) 

print t.interval 
# result: 0.0220727116414 

with Timer() as t: 
    for x in xrange(10000): 
     list(flattenIter([['a', 'b', 'c'], [1, 2, 3]])) 

print t.interval 
# result: 0.147218201587 

還檢查了:

Making a flat list out of list of lists in Python

它被標記爲重複,但它也有其他一些固定鏈接。 ;)