2016-02-27 51 views
0

通過討論Making a flat list out of list of lists in Python啓發我試圖將此轉換(獲取文件和文件夾的修改。在some_directory次):轉換嵌套列表理解使用itertools鏈蟒蛇

c = [os.path.getmtime(item) for root, d, files in os.walk(some_directory) 
     for item in [root] + map(lambda fi: os.path.join(root, fi), files)] 

要使用itertools.chain:

c = map(os.path.getmtime, 
     itertools.chain.from_iterable([root] + map(lambda fi: join(root, fi), files) 
             for root, d, files in os.walk(some_directory))) 

,但我的分析表明它是慢再加上看起來並不真正優雅。

所以,我怎麼可以用鏈在這種情況下,這是我更優雅(快)如何製作中間體名單?

或者是否還有一些其他itertools函數爲我的情況?

編輯:

散列了剖析腳本:

import timeit 

repeat = 10 

setup =""" 
import itertools 
import os 

join = os.path.join 
path = r'C:\Dropbox\eclipse_workspaces' 
c = [] 
""" 


print "Original    ", min(timeit.Timer("""[c.extend([join(root,dir) for dir in dirs] + [join(root,file) for file in files]) for root,dirs,files in os.walk(path)]""", 
         setup=setup).repeat(3, repeat)) 
print "For loop    ", min(timeit.Timer("""for root, d, files in os.walk(path): 
    c.append(root) 
    c.extend(join(root, fi) for fi in files)""", 
         setup=setup).repeat(3, repeat)) 
print "Comprehension  ", min(timeit.Timer('[item for r, d, f in os.walk(path) for item in [r] + map(lambda f: join(r, f), f)]', 
         setup=setup).repeat(3, repeat)) 
print "Comprehension + chain", min(timeit.Timer('[item for r, d, f in os.walk(path) for item in itertools.chain.from_iterable(([r], map(lambda fi: join(r, fi), f)))]', 
         setup=setup).repeat(3, repeat)) 
print "Itertools   ", min(timeit.Timer("""[j for j in itertools.chain.from_iterable([root] + map(lambda fi: join(root, fi), files) 
             for root, d, files in os.walk(path))]""", 
         setup=setup).repeat(3, repeat)) 

似乎沒有什麼區別,但剖析,所以我不發表任何結果,當我有一些奇怪的文物。我仍然對最快的方式感興趣,最好使用itertools

回答

2

我認爲在這裏使用chain並不合適。 chain壓扁時,它取代了修真的整點是最有用的。如果你正在做更復雜的事情,那麼只要堅持理解或生成器表達式可能會更容易。甚至解壓結構轉變爲一種明確的for循環,這可能讓你避免在當前的代碼之類的連接列表:

c = [] 
for root, d, files in os.walk(some_directory): 
    c.append(root) 
    c.extend(join(root, fi) for fi in files) 
+0

謝謝 - 我也能避免連接列表通過像'itertools.chain一些可怕的事情.from_iterable([root],map(lambda fi:join(root,fi),files)] for root,d,files in os.walk(path)))' - 我覺得我在itertools符號中錯過了一些東西 - 你能否重寫我的示例,避免使用'for root,d,files ....'? –

+0

是的,你可以使用一個額外的'chain'呼籲避免串聯,但是這將是醜陋的。我不認爲有'os.walk'輸出使用'chain'的優雅方法。他們只是不能很好地融合在一起。當你想要'root'名字以及文件時,情況會更糟。 – Blckknght