Python中如何对os.listdir返回的文件进行排序

3
如果您下载了多年的数据并以year_day.dat的格式存储在文件中,例如名为2014_1.dat的文件包含2014年1月1日的数据。我需要按日期顺序读取这些数据文件,从2014_1.dat、2014_2.dat、2014_3.dat一直到当年结束。它们在文件夹中按此顺序列出,但是当我创建目录中文件的列表时,它们被重新排序为2014_1.dat、2014_10.dat、2014_100.dat、2014_101.dat... 2014.199.dat、2014_2.dat。我认为我需要使用一个排序函数,但是如何强制对列出的文件按天数排序,以便我可以继续处理它们呢? 以下是到目前为止的代码:
import sys, os, gzip, fileinput, collections
# Set the input/output directories
wrkDir = "C:/LJBTemp"
inDir = wrkDir + "/Input"
outDir = wrkDir + "/Output"
# here we go
inList = os.listdir(inDir)  # List all the files in the 'Input' directory
print inList  #print to screen reveals 2014_1.dat.gz followed by 2014_10.dat.gz NOT    2014_2.dat.gz HELP
d = {}
for fileName in inList:     # Step through each input file 
    readFileName = inDir + "/" + fileName

    with gzip.open(readFileName, 'r') as f: #call built in utility to unzip file for reading
      for line in f:
          city, long, lat, elev, temp = line.split() #create dictionary
          d.setdefault(city, []).append(temp) #populate dictionary with city and associated temp data from each input file
          collections.OrderedDict(sorted(d.items(), key=lambda d: d[0])) # QUESTION? why doesn't this work
          #now collect and write to output file
outFileName = outDir + "/" + "1981_maxT.dat" #create output file in output directory with .dat extension
with open(outFileName, 'w') as f:
     for city, values in d.items():
        f.write('{} {}\n'.format(city, ' '.join(values)))

print "All done!!"
raw_input("Press <enter>") # this keeps the window open until you press "enter"
3个回答

2
如果您不介意使用第三方库,可以使用 natsort 库,该库专为此情况设计。
import natsort
inList = natsort.natsorted(os.listdir(inDir))

这应该能够处理所有数字排序,而无需担心细节。
您还可以使用ns.PATH选项使排序算法具有路径感知性:
from natsort import natsorted, ns
inList = natsorted(os.listdir(inDir), alg=ns.PATH)

充分披露,我是“natsort”的作者。

你是一个英雄! - Mase

0

如果你的所有文件都以“2014_”开头,请尝试这个:

sorted(inList, key = lambda k: int(k.split('_')[1].split('.')[0]))

否则,可以利用元组比较,首先按年份排序,然后按文件名的第二部分排序。
sorted(inList, key = lambda k: (int(k.split('_')[0]), int(k.split('_')[1].split('.')[0])))

非常感谢您的帮助。我在这个应用程序中使用了第三方排序库natsort,但会在另一个应用程序中尝试您的建议。 - MapleMatrix

0

dict.items 返回一个由 (key, item) 对组成的列表。

key 函数仅使用第一个元素 (d[0] => key => 城市)。

还有另一个问题: sorted 返回已排序的列表的副本,并不会就地对列表进行排序。此外,OrderedDict 对象被创建但没有分配给任何变量;实际上,在每次将项附加到列表时都不需要进行排序。

删除 ... sorted ... 行,并替换以下行:

with open(outFileName, 'w') as f:
     for city, values in d.items():
        f.write('{} {}\n'.format(city, ' '.join(values)))

使用以下代码将解决您的问题:

with open(outFileName, 'w') as f:
     for city, values in d.items():
        values.sort(key=lambda fn: map(int, os.path.splitext(fn)[0].split('_')))
        f.write('{} {}\n'.format(city, ' '.join(values)))

顺便提一下,不要手动连接硬编码的分隔符/,而是使用{{link1:os.path.join}}:

inDir + "/" + fileName

 =>

os.path.join(inDir, fileName)

感谢您的建议。values.sort解决方案确实可以将值按从大到小的顺序排序并在输出中打印出来。但是我想要做的是复制一种输出格式,以便每次运行代码时城市顺序保持不变。我有30年的输入数据,并需要使输出标准化以进行下一阶段的编码。 - MapleMatrix
@MapleMatrix,如果您还想按城市排序,请将 for city, values in d.items(): 替换为 for city, values in sorted(d.items()): - falsetru

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