Python 如何在v2.3中按第n个元素对列表排序?

Python 如何在v2.3中按第n个元素对列表排序?,python,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

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

#!/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   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
def format_seconds_since_epoch(t):
    if t == 3600:
        return "aborted"
    else:
        return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple())
(其中最后两个字段为历元时间)由下一个到最后一个字段排序:

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
如您所见,我使用了v2.4中引入的
sorted()
,如何重写v2.3的脚本,以使其执行相同的操作。 此外,我想将历元时间转换为人类可读的格式,因此生成的文件如下所示:

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   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
def format_seconds_since_epoch(t):
    if t == 3600:
        return "aborted"
    else:
        return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple())
我知道,这个
strftime(“%d/%m/%y%H:%m:%S”,gmtime())
可以用来转换历元时间,但我不知道如何将它应用到脚本中,以那种格式重写文件

评论?宝贵的忠告!
@Mark:Update

在某些情况下,大纪元时间为
3600
,表示未完成的业务。我想为这样一行打印中止,而不是
01/01/1970
。因此,我更改了
格式\u seconds\u,因为\u epoch()
如下:

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   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
def format_seconds_since_epoch(t):
    if t == 3600:
        return "aborted"
    else:
        return strftime("%d/%m/%y %H:%M:%S",datetime.fromtimestamp(t).timetuple())

解决了问题。在这方面,这是最好的做法吗?干杯

在回答您的最终查询时,您可以使用
datetime从
time\t
创建一个
datetime
对象,例如使用
datetime.fromtimestamp
,从“自历元起的秒数”值

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]
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)
因此,将其与稍加修改的版本结合起来,您的脚本可能如下所示:

#!/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
ing变量之后,避免使用
file
这个名称仍然是一种很好的方式。)

在回答关于特殊“3600”值的进一步问题时,您的解决方案很好。就我个人而言,我可能会保留
format\u seconds\u-since\u epoch
函数的原样,这样它就不会有令人惊讶的特殊情况,并且更普遍地有用。您可以使用特殊情况创建一个额外的包装函数,或者只需将
split\u line[i]=format\u seconds\u since\u epoch(int(split\u line[i]))
行更改为:

entry = int(split_line[i])
if entry == 3600:
    split_line[i] = "aborted"
else:
    split_line[i] = format_seconds_since_epoch(entry)
。。。然而,我不认为有什么不同


顺便说一句,如果这不仅仅是一项一次性任务,我想看看你是否可以在2系列中使用比2.3更高版本的Python,现在已经相当旧了——它们有很多很好的特性,可以帮助你编写更干净的脚本。

在回答你的最后一个查询时,你可以从
时间创建
对象,比如使用
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)
因此,将其与稍加修改的版本结合起来,您的脚本可能如下所示:

#!/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
请注意,使用
文件
作为变量名是个坏主意,因为它会隐藏内置的
文件
类型,所以我将它们更改为
fin
fout
(即使您在之后删除变量,我认为避免使用
文件
名称仍然是一种很好的方式。)

在回答您关于“3600”特别版的进一步问题时“值,您的解决方案很好。就我个人而言,我可能会保留
format\u seconds\u-since\u epoch
函数的原样,这样它就不会有令人惊讶的特殊情况,并且更普遍地有用。您可以使用特殊情况创建一个额外的包装函数,或者只需将
split\u line[i]=format\u seconds\u since\u epoch(int(split\u line[i]))
行更改为:

entry = int(split_line[i])
if entry == 3600:
    split_line[i] = "aborted"
else:
    split_line[i] = format_seconds_since_epoch(entry)
。。。然而,我不认为有什么不同


顺便说一句,如果这不仅仅是一项一次性任务,我想看看您是否可以在2系列中使用比2.3更高版本的Python,而2.3现在已经相当旧了-它们有很多很好的功能,可以帮助您编写更干净的脚本。

一些小事情:1。OP的文件由选项卡分隔,而不是单个空格2。您需要比较最后第二列,而不是第三列3。可能最好在比较之前将列值转换为数字,以防某些值是2001年9月之前的倍:)一些小事情:1。OP的文件由选项卡分隔,而不是单个空格2。您需要比较最后第二列,而不是第三列3。可能最好在比较之前将列值转换为数字,以防某些值是2001年9月之前的倍:)@mark:非常感谢。稍后我将测试脚本(生成实际的输入文件需要一点时间),并很快在这里报告。是的,使用
文件
作为变量名是个坏主意,我确实犯了错误。谢谢你指出。干杯@马克:效果非常好。谢谢你的快速重播。干杯@马克:嗯,有一个小问题:有时候,最后一个字段显示为“3600”,这意味着某项工作没有成功完成。对于这样的行,如何打印例如“中止”而不是
01/01/70 02:00:00
?干杯@马克:我已经解决了“3600”问题,修改了格式\u seconds\u since\u epoch()函数;更新了我原来的帖子。不确定这是不是最好的方法。干杯@MacUsers:没问题-我已经用另一个建议更新了我的答案,但是你的答案看起来不错。(我还将元组中的索引改为-2,-1,而不是3,4,因为你说它们总是最后两列。)@mark:非常感谢。稍后我将测试脚本(生成实际的输入文件需要一点时间),并很快在这里报告。是的,使用
文件
作为变量名是个坏主意,我确实犯了错误。谢谢你指出。干杯@马克:效果非常好。谢谢你的快速重播。干杯@马克:嗯,有一个小问题:有时候,最后一个字段显示为“3600”,这意味着某项工作没有成功完成。对于这样的行,如何打印例如“中止”而不是
01/01/70 02:00:00
?干杯