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

发布于 2024-10-27 16:21:14 字数 638 浏览 1 评论 0原文

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

In Python, I want to list all files in a set of directories. The best I'd like to get is a list. But at most I managed to make a nested list:

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

result:

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

what I want:

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

What I would like to get is a simple plain list, doesn't matter of what (can be of tuples), just so that it hasn't nested things, and I need no nested cycles in the code that parses it.

How can I do this with list comprehensions? Doing this gives me a product of 2 sets (dir names and filenames) which is wrong:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

彩扇题诗 2024-11-03 16:21:14

您的 for 循环顺序错误。它应该是

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

最外层循环在前,最内层循环在最后。

我想知道为什么你没有得到 dNameError

You got the order of the for-loops wrong. It should be

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

Outermost loop first, innermost loop last.

I wonder why you didn't get a NameError for d.

软甜啾 2024-11-03 16:21:14

使用 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]不是目录
  • 它更简单:os.walk为你做遍历,所有剩下的就是格式化输出

Using os.walk is a better idea:

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

So why is it a better idea?

  • it works with deeper trees, too (subdir/subdir/pic.jpg)
  • it doesn't break if you put a file in ~/Pictures (If you call os.listdir on files, you get OSError: [Errno 20] Not a directory)
  • it's simpler: os.walk does the traversing for you, all that remains is formatting the output
留一抹残留的笑 2024-11-03 16:21:14

列表推导式作为从一个列表到另一个列表的映射。正如另一张海报指出的那样,您可以通过嵌套它们来做到这一点,但您确定您真的想要这样做吗?在大多数情况下,您应该优先考虑可读性 - 而且我不认为嵌套理解很容易理解。

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

List comprehensions work as a mapping from one list to another. As another poster pointed it you can do it by nesting them, but are you sure you really want to? You should favour readability over everything else, in all most all cases - and I don't consider the nested comprehension to be easily understandable.

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

If you don't want to generate the list until absolutely necessary you could use a generator:

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())
遥远的她 2024-11-03 16:21:14

您只需要展平您的输出列表:

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

You simply need to flatten your output list:

pics = os.path.expanduser('~/Pictures')
all_pics = reduce(lambda xs,ys: xs+ys, [(d, os.listdir(d)) for d in os.listdir(pics)])
请帮我爱他 2024-11-03 16:21:14
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文