如何在不制作产品的情况下进行嵌套列表理解?

时间:2011-03-30 10:30:17

标签: python list-comprehension

在Python中,我想列出一组目录中的所有文件。我想得到的最好的是一个列表。但最多我设法制作了一个嵌套列表:

pics = os.path.expanduser('~/Pictures')
all_pics = [(d, os.listdir(d)) for d in os.listdir(pics)]

结果:

[('folder1', ['file1', 'file2', ...]), ('folder2', ['file1', ...]), ...]

我想要的是什么:

[('folder1' 'file1'), ('folder1', 'file2'), ..., ('folder2', 'file1'), ...]

我想得到的是一个简单的普通列表,无论是什么(可以是元组),只是为了它没有嵌套的东西,我在解析它的代码中不需要嵌套循环

如何使用列表推导来完成此操作?这样做给了我2套(目录名和文件名)的产品,这是错误的:

[(d, f) for f in os.listdir(os.path.join(pics, d)) for d in os.listdir(pics)]

5 个答案:

答案 0 :(得分:5)

你得到了for循环的顺序错误。它应该是

all_pics = [(d, f)
            for d in os.listdir(pics)
            for f in os.listdir(os.path.join(pics, d))]

最外面的循环,最里面的循环。

我想知道为什么你没有为NameError获得d

答案 1 :(得分:4)

使用os.walk是一个更好的主意:

all_pics = [(dir,file)
            for dir,sub,files in os.walk(pics) 
            for file in files]

那么为什么这是一个更好的主意呢?

  • 它也适用于更深的树木(subdir/subdir/pic.jpg
  • 如果您将文件放在~/Pictures中,则不会中断(如果您在文件上调用os.listdir,则会获得OSError: [Errno 20] Not a directory
  • 更简单:os.walk为您进行遍历,剩下的就是格式化输出

答案 2 :(得分:1)

列表推导作为从一个列表到另一个列表的映射。正如另一张海报所指出的,你可以通过嵌套它们来做到这一点,但你确定你真的想要吗?在大多数情况下,你应该倾向于阅读所有其他内容 - 而且我不认为嵌套理解很容易理解。

What is wrong with? It might be marginally slower - but will you notice?

files = []
for d in os.listdir(pics):
    for f in os.listdir(os.path.join(pics, d)):
        files.append((d, f))

如果您不想在绝对必要之前生成列表,则可以使用生成器:

def get_file_mapping():
    for d in os.listdir(pics):
        for f in os.listdir(os.path.join(pics, d)):
            yield (d, f)
files = list(get_file_mapping())

答案 3 :(得分:0)

l = [ [(d, f) for f in os.listdir(os.path.join(pics, d))] for d in os.listdir(pics) ]
l = sum(l, []) # flatten list of lists => list

答案 4 :(得分:0)

您只需要展平输出列表:

pics = os.path.expanduser('~/Pictures')
all_pics = reduce(lambda xs,ys: xs+ys, [(d, os.listdir(d)) for d in os.listdir(pics)])