2

I wanted to gather all of the header files in a list of subdirectories. However, if I do

from glob import glob
from itertools import chain

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

What I get is

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

But what I wanted to see was

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

I thought that was what the chain() would do for me. What am I missing?

4

2 回答 2

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

它展平了一个可迭代的迭代:

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]
于 2013-02-11T20:30:11.713 回答
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

另请查看:

从 Python 中的列表列表中制作一个平面列表

它被标记为重复,尽管其中也有一些其他可靠的链接。;)

于 2013-02-11T20:37:43.583 回答