如何控制Python中迭代器结果的顺序?

22

我使用 pathlib.Path().iterdir() 方法来获取路径下的子目录。

/home/yuanyi/workspace/app 下,有四个文件夹:01020304

from pathlib import Path
for subdir in Path('/home/yuanyi/workspace/app').iterdir():
    print(subdir)

但结果没有被排序。

/home/yuanyi/workspace/app/02
/home/yuanyi/workspace/app/03
/home/yuanyi/workspace/app/01
/home/yuanyi/workspace/app/00

为什么结果不是以下内容:

/home/yuanyi/workspace/app/01
/home/yuanyi/workspace/app/02
/home/yuanyi/workspace/app/03
/home/yuanyi/workspace/app/04

我想了解迭代器的工作原理,并了解获取有序结果的最佳方法。


1
你用的是哪个操作系统? - Ray
1
Path.iterdir() 文档 中可以看到:"子项以任意顺序生成..." - djvg
2个回答

32
你可以使用 "sorted()"。 内置函数 Python - sorted()
from pathlib import Path
for subdir in sorted(Path('/some/path').iterdir()):
    print(subdir)

注意: @NamitJuneja 指出,这将迭代生成器更改为迭代列表。因此,如果内存中有大量文件,则将它们全部加载到内存中(通过将它们加载到列表中)可能会导致问题。

在我的Mac上,iterdir()方法返回已排序的列表。所以这看起来是系统相关的。您使用的是什么操作系统?


3
这会将遍历生成器变为遍历列表。因此,如果内存中有大量文件,则将它们全部加载到内存中(通过将它们加载到列表中)可能会导致问题。 - Namit Juneja
谢谢@NamitJuneja,我已经将你的评论加入到答案中了。请随意编辑! - Tim Grant

3

我认为你应该从这个结果中找出答案。

>>> l = ['/home/yuanyi/workspace/app/02',
'/home/yuanyi/workspace/app/03', '/home/yuanyi/workspace/app/01']
>>> for i in sorted(l, key=lambda m: int(m.split('/')[-1])):
    print i


/home/yuanyi/workspace/app/01
/home/yuanyi/workspace/app/02
/home/yuanyi/workspace/app/03
>>> 

或者

for i in sorted(l, key=lambda m: int(m.split(os.sep)[-1])):
    print i

那么,你的意思是我需要做一些其他工作来排序吗?有没有迭代器的方法可以获得有序的结果? - wuyuanyi
非常不错的尝试,但只有os.walk()可以保证自上而下的顺序。我相信这是一个小例子,但这可能是发帖者所期望的。不幸的是,Pathlib的任何变体都不能提供此保证,因此用户必须实现自己的排序。如何进行自上而下的排序? - ingyhere
1
啊,是的,我通过查看Python源代码找到了答案:所以iterdir()使用listdir()glob()使用scandir()。Scandir是从os模块中提取出来的。由于os.walk()也使用scandir(),因此看起来最接近os.walk()的东西是pathlib.glob(),但我不确定如何将其用于使输出看起来像os.walk()(艺术)。如果您想知道为什么Pathlib的某些部分使用listdir(),那是由Guido裁决的(https://mail.python.org/pipermail/python-dev/2013-November/130583.html)。 - ingyhere

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接