来自os.listdir()的非字母数字列表顺序

mar*_*ard 92 python list directory-listing listdir

我经常使用python来处理数据目录.最近,我注意到列表的默认顺序已经变为几乎荒谬的东西.例如,如果我在包含以下子目录的当前目录中:run01,run02,... run19,run20,然后我从以下命令生成一个列表:

dir = os.listdir(os.getcwd())
Run Code Online (Sandbox Code Playgroud)

然后我通常按此顺序获得一个列表:

dir = ['run01', 'run18', 'run14', 'run13', 'run12', 'run11', 'run08', ... ]
Run Code Online (Sandbox Code Playgroud)

等等.订单曾经是字母数字.但是这个新订单现在已经和我保持了一段时间.

什么是确定这些列表的(显示)顺序?

mgi*_*son 106

您可以使用内置sorted函数对字符串进行排序.根据你的描述,

sorted(os.listdir(whatever_directory))
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用.sort列表的方法:

lst = os.listdir(whatever_directory)
lst.sort()
Run Code Online (Sandbox Code Playgroud)

我认为应该做的伎俩.

请注意,os.listdir获取文件名的顺序可能完全取决于您的文件系统.

  • 只有`sorted(listdir)`对我有用.`listdir.sort()`给了我:TypeError:'NoneType'对象不可迭代 (3认同)
  • @paul_h - `listdir.sort()` 对于像 `for i in listdir.sort()` 这样的语句不起作用,因为 `list.sort()` 方法改变了列表中项目的顺序 **IN PLACE* *,这意味着处理列表本身,但除了“None”之外不会返回任何内容。所以你需要使用 `a_list = listdir('some_path'); a_list.sort()` 然后执行 `for i in a_list` (3认同)
  • 如果处理数字优先的文件名,则不会更改顺序(即 59.9780radps-0096 仍位于 9.9746radps-0082 之前)。我认为这是因为一切都是字符串,所以小数点没有得到正确的处理。 (2认同)
  • 或者使用我刚刚找到的natsort库. (2认同)

Now*_*ayz 55

我认为订单与FileSystem上的文件索引方式有关.如果您真的想让它遵守某些订单,您可以在获取文件后始终对列表进行排序.


Mar*_*nen 40

根据文件:

os.listdir(路径)

返回一个列表,其中包含path给出的目录中的条目名称.该列表按任意顺序排列.它不包括特殊条目'.' 和'..'即使它们存在于目录中.

订单不能依赖,是文件系统的工件.

要对结果进行排序,请使用sorted(os.listdir(path)).


use*_*036 17

无论出于何种原因,Python都没有内置的自然排序方式(意思是1,2,10而不是1,10,2),所以你必须自己编写:

import re
def sorted_aphanumeric(data):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(data, key=alphanum_key)
Run Code Online (Sandbox Code Playgroud)

您现在可以使用此功能对列表进行排序:

dirlist = sorted_aphanumeric(os.listdir(...))
Run Code Online (Sandbox Code Playgroud)


小智 17

我认为默认情况下,顺序是由 ASCII 值确定的。这个问题的解决方案是这样的

dir = sorted(os.listdir(os.getcwd()), key=len)
Run Code Online (Sandbox Code Playgroud)

  • 上述方法都不适合我,“key-len”似乎是最后剩下的技巧,非常感谢。 (2认同)

roc*_*yne 7

使用natsort库:

使用以下命令为 Ubuntu 和其他 Debian 版本安装库

蟒蛇 2

sudo pip install natsort
Run Code Online (Sandbox Code Playgroud)

蟒蛇 3

sudo pip3 install natsort
Run Code Online (Sandbox Code Playgroud)

可以在此处找到有关如何使用此库的详细信息

sudo pip install natsort
Run Code Online (Sandbox Code Playgroud)
  • 这不是answer的副本。于 2020 年natsort1月 27 日作为编辑添加。

  • 这比 `sorted()` 更准确!谢谢 (2认同)

Mik*_*one 5

这可能只是C的readdir()回归顺序.尝试运行此C程序:

#include <dirent.h>
#include <stdio.h>
int main(void)
{   DIR *dirp;
    struct dirent* de;
    dirp = opendir(".");
    while(de = readdir(dirp)) // Yes, one '='.
        printf("%s\n", de->d_name);
    closedir(dirp);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

构建线应该是这样的gcc -o foo foo.c.

PS刚刚运行了这个和你的Python代码,他们都给了我排序的输出,所以我无法重现你所看到的.


raj*_*cis 5

aaa = ['row_163.pkl', 'row_394.pkl', 'row_679.pkl', 'row_202.pkl', 'row_1449.pkl', 'row_247.pkl', 'row_1353.pkl', 'row_749.pkl', 'row_1293.pkl', 'row_1304.pkl', 'row_78.pkl', 'row_532.pkl', 'row_9.pkl', 'row_1435.pkl']                                                                                                                                                                                                                                                                                                 
sorted(aaa, key=lambda x: int(os.path.splitext(x.split('_')[1])[0]))
Run Code Online (Sandbox Code Playgroud)

如果按照我的要求,我有像row_163.pkl这里这样的情况,因此需要根据“_”将其拆分os.path.splitext('row_163.pkl')('row_163', '.pkl')

但如果您有要求,您可以这样做

sorted(aa, key = lambda x: (int(re.sub('\D','',x)),x))
Run Code Online (Sandbox Code Playgroud)

在哪里

aa = ['run01', 'run08', 'run11', 'run12', 'run13', 'run14', 'run18']
Run Code Online (Sandbox Code Playgroud)

对于目录检索,你可以这样做sorted(os.listdir(path))

对于类似的情况'run01.txt'或者'run01.csv'你可以这样做

sorted(files, key=lambda x : int(os.path.splitext(x)[0]))
Run Code Online (Sandbox Code Playgroud)