如何按v2.3中的第n个元素对列表进行排序?

时间:2011-02-26 09:59:51

标签: python

这是我写的一个简单的脚本:

#!/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(),这是在v2.4中引入的,我如何重写v2.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,表示未完成的业务。我想打印中止而不是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 个答案:

答案 0 :(得分:4)

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]

答案 1 :(得分:1)

在回复您的最终查询时,您可以使用datetimetime_t创建一个datetime.fromtimestamp对象 - 例如“自纪元以来的秒数”值,例如

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's answer的略微修改版本放在一起,您的脚本可能如下所示:

#!/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类型,因此我将其更改为finfout 。 (即使你事后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系列中使用更高版本的Python而不是2.3,现在已经很老了 - 它们有很多很好的功能可以帮助一个写清洁脚本。