简体   繁体   English

转换嵌套列表推导以在python中使用itertools链

[英]Convert nested list comprehension to use itertools chain in python

Inspired by the discussion in Making a flat list out of list of lists in Python I tried to convert this (getting files and folders modification times in some_directory): 受到在Python列表列表之外制作平面列表中的讨论的启发,我尝试进行转换(在some_directory中获取文件和文件夹的修改时间):

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)]

To use itertools.chain: 要使用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)))

but my profiling shows it to be slower plus does not look really elegant. 但我的剖析显示它速度较慢,而且看起来并不优雅。

So how can I use chain in this case, that is how can I more elegantly (and faster) produce the intermediate lists ? 因此,在这种情况下,如何使用链,也就是如何更好地(更快)生成中间列表?

Or is there some other itertools function for my case ? 还是我的情况下还有其他itertools函数?

EDIT: 编辑:

Hashed up a profiling script: 整理了一个分析脚本:

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

seems there is no difference but I had some strange artifacts when profiling so I don't post any results. 似乎没有什么区别,但分析时我有一些奇怪的工件,因此我不发布任何结果。 I am still interested in the fastest way that can be done, preferably using itertools 我仍然对最快的方法感兴趣,最好使用itertools

I don't think it makes sense to use chain here. 我认为在这里使用chain没有意义。 chain is most useful when flattening is the whole point of the comprehension it's replacing. 当扁平化是要替换的理解的全部内容时, chain最有用。 If you're doing more complicated stuff, then it's probably easier just to stick with a comprehension or generator expression. 如果您正在做更复杂的事情,那么坚持理解或生成器表达式可能会更容易。 Or even unpack the structure into an explicit for loop, which might allow you to avoid things like the list concatenation in your current code: 甚至将结构解压缩到显式的for循环中,这可能使您避免在当前代码中使用列表串联之类的方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM