如何按第n个元素在v2.3中排序列表?
这是我写的一个简单脚本:
#!/usr/bin/env python
file = open('readFile.txt', 'r')
lines = file.readlines()
file.close()
del file
sortedList = sorted(lines, key=lambda lines: lines.split('\t')[-2])
file = open('outfile.txt', 'w')
for line in sortedList:
file.write(line)
file.close()
del file
它的功能是把一个文件改成这样的格式:
161788 group_monitor.sgmops 4530 1293840320 1293840152
161789 group_atlas.atlas053 22350 1293840262 1293840152
161790 group_alice.alice017 210 1293840254 1293840159
161791 group_lhcb.pltlhc15 108277 1293949235 1293840159
161792 group_atlas.sgmatlas 35349 1293840251 1293840160
(其中最后两个字段是时间戳)按倒数第二个字段的顺序排列成这样:
161792 group_atlas.sgmatlas 35349 1293840251 1293840160
161790 group_alice.alice017 210 1293840254 1293840159
161789 group_atlas.atlas053 22350 1293840262 1293840152
161788 group_monitor.sgmops 4530 1293840320 1293840152
161791 group_lhcb.pltlhc15 108277 1293949235 1293840159
如你所见,我使用了 sorted()
函数,这个函数是在版本2.4中引入的。我想知道如何把这个脚本改成适用于2.3版本,以实现同样的功能。
另外,我还想把时间戳转换成普通人能看懂的格式,这样生成的文件看起来像这样:
161792 group_atlas.sgmatlas 35349 01/01/11 00:04:11 01/01/11 00:02:40
161790 group_alice.alice017 210 01/01/11 00:04:14 01/01/11 00:02:39
161789 group_atlas.atlas053 22350 01/01/11 00:04:22 01/01/11 00:02:32
我知道可以用 strftime("%d/%m/%y %H:%M:%S", gmtime())
来转换时间戳,但我就是搞不清楚怎么把它应用到脚本中,以便把文件改成那种格式。
有什么意见或建议吗?非常感谢!
@Mark: 更新
在某些情况下,时间戳是 3600
,这表示某个任务没有完成。我想在这种情况下打印 aborted,而不是 01/01/1970
。所以,我把 format_seconds_since_epoch()
改成了这样:
def format_seconds_since_epoch(t):
if t == 3600:
return "aborted"
else:
return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple())
这样就解决了这个问题。这是能做的最好的吗?谢谢!!
2 个回答
针对你最后的问题,你可以通过 datetime.fromtimestamp
从类似 time_t
的“自纪元以来的秒数”值创建一个 datetime
对象,比如:
from datetime import datetime
from time import strftime
def format_seconds_since_epoch(t):
return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple())
print format_seconds_since_epoch(1293840160)
所以,把这个和稍微修改过的 pynator的回答结合起来,你的脚本可能看起来像这样:
#!/usr/bin/env python
from datetime import datetime
from time import strftime
import os
def format_seconds_since_epoch(t):
return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple())
fin = open('readFile.txt', 'r')
lines = fin.readlines()
fin.close()
del fin
split_lines = [ line.split("\t") for line in lines ]
split_lines.sort( lambda a, b: cmp(int(a[-2]),int(b[-2])) )
fout = open('outfile.txt', 'w')
for split_line in split_lines:
for i in (-2,-1):
split_line[i] = format_seconds_since_epoch(int(split_line[i]))
fout.write("\t".join(split_line)+os.linesep)
fout.close()
del fout
注意,使用 file
作为变量名并不好,因为它会覆盖内置的 file
类型,所以我把它们改成了 fin
和 fout
。(即使你之后用 del
删除这些变量,我觉得避免使用 file
这个名字还是个好习惯。)
关于你进一步询问的特殊“3600”值,你的解决方案是可以的。就我个人而言,我可能会保持 format_seconds_since_epoch
函数不变,这样就不会有让人意外的特殊情况,并且更通用。你可以创建一个额外的包装函数来处理这个特殊情况,或者只需将 split_line[i] = format_seconds_since_epoch(int(split_line[i]))
这一行改成:
entry = int(split_line[i])
if entry == 3600:
split_line[i] = "aborted"
else:
split_line[i] = format_seconds_since_epoch(entry)
... 不过我觉得两者之间的差别不大。
顺便说一下,如果这不是一次性的任务,我建议你使用比 2.3 更高版本的 Python 2 系列,因为 2.3 现在已经相当老了——新版本有很多不错的功能,可以帮助你写出更简洁的脚本。
file = open('readFile.txt', 'r')
lines = file.readlines()
file.close()
del file
lines = [line.split(' ') for line in lines]
lines.sort(lambda x,y: cmp(x[2], y[2])
lines = [' '.join(line) for line in lines]
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。