根据月份和年份算法生成文件名列表
我想列出从 01
到 12
的数字(每个月一个),但是要让当前月份总是排在最后,最老的月份排在最前面。换句话说,如果数字大于当前月份,那就是去年对应的月份。
比如说,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 个回答
你的问题我有点难理解。
如果你只是想把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()
方法中放入合适的文件名格式...
希望这正是你想要的...
第三次更新:
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
这个系统更好,至少在后端是这样。
你不能打印一个已经排序的列表,除非你先对这个列表进行排序!我觉得修改你的代码最简单的方法是先获取文件名,然后对它们进行排序,最后再对排序后的列表进行操作。通过把年份和月份按这个顺序放在一个元组里,排序就会自动给你正确的顺序。
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)]
...