根据月份和年份算法生成文件名列表

3 投票
3 回答
2102 浏览
提问于 2025-04-16 11:47

我想列出从 0112 的数字(每个月一个),但是要让当前月份总是排在最后,最老的月份排在最前面。换句话说,如果数字大于当前月份,那就是去年对应的月份。

比如说,02 代表的是2011年2月(现在的月份),03 代表的是2010年3月,09 代表的是2010年9月,而 01 代表的是2011年1月。在这种情况下,我想要的结果是 [09, 03, 01, 02]。这是我用来确定年份的代码:

for inFile in os.listdir('.'):
    if inFile.isdigit():
    month = months[int(inFile)]
       if int(inFile) <= int(strftime("%m")):
           year = strftime("%Y")
       else:
           year = int(strftime("%Y"))-1
       mnYear = month + ", " + str(year)

接下来我不知道该怎么做。请问我该怎么办呢?


更新:

我觉得我最好上传整个脚本,这样更容易理解。

#!/usr/bin/env python

import os, sys
from time import strftime
from calendar import month_abbr

vGroup = {}
vo = "group_lhcb"
SI00_fig = float(2.478)
months = tuple(month_abbr)

print "\n%-12s\t%10s\t%8s\t%10s" % ('VOs','CPU-time','CPU-time','kSI2K-hrs')
print "%-12s\t%10s\t%8s\t%10s" % ('','(in Sec)','(in Hrs)','(*2.478)')
print "=" * 58

for inFile in os.listdir('.'):
    if inFile.isdigit():
        readFile = open(inFile, 'r')
        lines = readFile.readlines()
        readFile.close()

        month = months[int(inFile)]
        if int(inFile) <= int(strftime("%m")):
            year = strftime("%Y")
        else:
            year = int(strftime("%Y"))-1
        mnYear = month + ", " + str(year)

        for line in lines[2:]:
            if line.find(vo)==0:
                g, i = line.split()
                s = vGroup.get(g, 0)
                vGroup[g] = s + int(i)

        sumHrs = ((vGroup[g]/60)/60)
        sumSi2k = sumHrs*SI00_fig
        print "%-12s\t%10s\t%8s\t%10.2f" % (mnYear,vGroup[g],sumHrs,sumSi2k)
        del vGroup[g]

当我运行这个脚本时,我得到的是:

[root@serv07 usage]# ./test.py 

VOs               CPU-time  CPU-time     kSI2K-hrs
                  (in Sec)  (in Hrs)      (*2.478)
==================================================
Jan, 2011        211201372     58667     145376.83
Dec, 2010          5064337      1406       3484.07
Feb, 2011         17506049      4862      12048.04
Sep, 2010        210874275     58576     145151.33

正如我在最初的帖子中所说,我希望结果按这个顺序排列:

Sep, 2010        210874275     58576     145151.33
Dec, 2010          5064337      1406       3484.07
Jan, 2011        211201372     58667     145376.83
Feb, 2011         17506049      4862      12048.04

源目录中的文件是这样的:

[root@serv07 usage]# ls -l
total 3632
-rw-r--r--  1 root root 1144972 Feb  9 19:23 01
-rw-r--r--  1 root root  556630 Feb 13 09:11 02
-rw-r--r--  1 root root  443782 Feb 11 17:23 02.bak
-rw-r--r--  1 root root 1144556 Feb 14 09:30 09
-rw-r--r--  1 root root  370822 Feb  9 19:24 12

这样我是不是更清楚了?抱歉一开始没有说得很明白。谢谢!!


更新 @Mark Ransom

这是根据Mark的建议得到的结果:

[root@serv07 usage]# ./test.py 

VOs               CPU-time  CPU-time     kSI2K-hrs
                  (in Sec)  (in Hrs)      (*2.478)
==========================================================
Dec, 2010          5064337      1406       3484.07
Sep, 2010        210874275     58576     145151.33
Feb, 2011         17506049      4862      12048.04
Jan, 2011        211201372     58667     145376.83

正如我之前所说,我希望结果按这个顺序打印:2010年9月 -> 2010年12月 -> 2011年1月 -> 2011年2月。谢谢!!

3 个回答

0

你的问题我有点难理解。

如果你只是想把12个月的数字旋转一下,让当前月份的数字放到最后,这段代码可以做到:

>>> def rot_list(l,n):
...    return l[n:]+l[:n]
... 
>>> rot_list(range(1,13),2)
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2]

如果你想要的结果是一个目标列表(就像你举的例子)排序后旋转,让离当前月份(用n表示)最近的数字在最后,这段代码可以实现:

>>> tar=[1,2,3,9]
>>> n=2
>>> [x for x in range(1,13)[n:]+range(1,13)[:n] if x in tar]
[3, 9, 1, 2]
>>> tar=[3,1,2,9]
>>> [x for x in range(1,13)[n:]+range(1,13)[:n] if x in tar]
[3, 9, 1, 2]

现在,如果你需要这个列表前面有零,并且每个元素都是字符串的话:

>>> nm=[3,9,1,2]
>>> fn=['%02i' % x for x in nm]
>>> fn
['03', '09', '01', '02']

这些方法都可以用,不管一月是'0'还是'1'。只需要根据你的习惯,把range(1,13)改成range(0,12)就行。

编辑

如果我理解你在做的事情,这段代码会对你有帮助:

import datetime

def prev_month(year,month,day):
    l=range(1,13)
    l=l[month:]+l[:month]
    p_month=l[10]
    if p_month>month:
        p_year=year-1
    else:
        p_year=year
    return (p_year,p_month,1)

def next_month(year,month,day):
    l=range(1,13)
    l=l[month:]+l[:month]
    p_month=l[0]
    if p_month<month:
        p_year=year+1
    else:
        p_year=year
    return (p_year,p_month,1)

year=2011
month=2
t=(year-1,month,1)
ds=[]
for i in range(1,13):
    print datetime.date(*t).strftime('%m, %y')
    t=next_month(*t)

输出:

02, 10
03, 10
04, 10
05, 10
06, 10
07, 10
08, 10
09, 10
10, 10
11, 10
12, 10
01, 11

只需要在strftime()方法中放入合适的文件名格式...

希望这正是你想要的...

1

第三次更新:

import os, sys
from time import strftime
from calendar import month_abbr

thismonth = int(strftime("%m"))
sortedmonths = ["%02d" % (m % 12 + 1) for m in range(thismonth, thismonth + 12)]
inFiles = [m for m in sortedmonths if m in os.listdir('.')]

for inFile in inFiles:
    readFile = open(inFile, 'r')
    # [ ... everything else is the same from here (but reindented)... ]

列表推导式更好用,但如果我做的事情在2.3版本中不太合适,可以试试这个:

inFiles = filter(lambda x: x.isdigit(), os.listdir('.'))
sortedmonths = map(lambda x: "%02d" % (x % 12 + 1), range(thismonth, thismonth + 12))
inFiles = filter(lambda x: x in inFiles, sortedmonths)

第二次更新:

好的,根据你的修改,我觉得这是最简单的解决方案:

import os, sys
from time import strftime
from calendar import month_abbr

thismonth = int(strftime("%m"))
inFiles = []
for inFile in os.listdir('.'):
    if inFile.isdigit():
        inFiles.append(inFile)
inFiles.sort(key=lambda x: (int(x) - thismonth - 1) % 12)

for inFile in inFiles:
    readFile = open(inFile, 'r')
    # [ ... everything else is the same from here (but reindented)... ]

这样你的主循环就能按正确的顺序处理文件了。

你还可以用一行的推导式替代上面的四行循环:

inFiles = [inFile for inFile in os.listdir('.') if inFile.isdigit()]

另外,我建议使用 from datetime import datetime,然后用 datetime.now()。这个用法比 strftime() 更好用—— datetime.now().month 会返回一个数字表示月份(.year.min.second 等也是如此),而 str(datetime.now()) 则会给出格式很好的日期时间字符串。

更新:

好的,经过一些调整,我觉得这个方法效果最好——无论 Jan = 1 还是 Jan = 0 都能用:

>>> themonths = [1, 2, 3, 9]
>>> themonths.sort(key=lambda x: (x - thismonth - 1) % 12)
>>> themonths
[2, 3, 9, 1]

原始帖子:

如果我理解得没错:

>>> thismonth = 1
>>> [m % 12 for m in range(thismonth + 1, thismonth + 13)]
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1]

或者如果你只想要某几个月,可以这样做:

>>> thismonth = 1
>>> themonths = [0, 1, 2, 8]
>>> [m % 12 for m in range(thismonth + 1, thismonth + 13) if m % 12 in themonths]
[2, 8, 0, 1]

注意在这个方案中 Jan = 0 .... Dec = 11。如果你想让 Jan = 1,可以在结果数字上加1(也就是说 [m % 12 + 1 for ... if m % 12 + 1 in themonths])。不过我觉得 Jan = 0 这个系统更好,至少在后端是这样。

1

你不能打印一个已经排序的列表,除非你先对这个列表进行排序!我觉得修改你的代码最简单的方法是先获取文件名,然后对它们进行排序,最后再对排序后的列表进行操作。通过把年份和月份按这个顺序放在一个元组里,排序就会自动给你正确的顺序。

filelist = []
for inFile in os.listdir('.'):
    if inFile.isdigit():
        if int(inFile) <= int(strftime("%m")):
            year = strftime("%Y")
        else:
            year = int(strftime("%Y"))-1
        filelist.append((year, inFile))
filelist.sort()
for year, inFile in filelist:
    month = months[int(inFile)]
    ...

撰写回答