OpenJudge百练第2998号习题:日志排序
题目描述
来源
OpenJudge网站 —— 百练习题集-第2998号习题
要求
总时间限制: 1000ms 内存限制: 65536kB
描述
有一个网络日志,记录了网络中计算任务的执行情况,每个计算任务对应一条如下形式的日志记录:“hs_10000_p”是计算任务的名称,“2007-01-17 19:22:53,315”是计算任务开始执行的时间“年-月-日 时:分:秒,毫秒”, “253.035(s)”是计算任务消耗的时间(以秒计)
hs_10000_p 2007-01-17 19:22:53,315 253.035(s)
请你写一个程序,对日志中记录计算任务进行排序。时间消耗少的计算任务排在前面,时间消耗多的计算任务排在后面。如果两个计算任务消耗的时间相同,则将开始执行时间早的计算任务排在前面。
输入
日志中每个记录是一个字符串,每个字符串占一行。最后一行为空行,表示日志结束。日志中最多可能有10000条记录。
计算任务名称的长度不超过10,开始执行时间的格式是YYYY-MM-DD HH:MM:SS,MMM,消耗时间小数点后有三位数字。
计算任务名称与任务开始时间、消耗时间之间以一个或多个空格隔开,行首和行尾可能有多余的空格。
输出
排序好的日志记录。每个记录的字符串各占一行。
输入的格式与输入保持一致,输入包括几个空格,你的输出中也应该包含同样多的空格。
样例输入
hs_10000_p 2007-01-17 19:22:53,315 253.035(s)
hs_10001_p 2007-01-17 19:22:53,315 253.846(s)
hs_10002_m 2007-01-17 19:22:53,315 129.574(s)
hs_10002_p 2007-01-17 19:22:53,315 262.531(s)
hs_10003_m 2007-01-17 19:22:53,318 126.622(s)
hs_10003_p 2007-01-17 19:22:53,318 136.962(s)
hs_10005_m 2007-01-17 19:22:53,318 130.487(s)
hs_10005_p 2007-01-17 19:22:53,318 253.035(s)
hs_10006_m 2007-01-17 19:22:53,318 248.548(s)
hs_10006_p 2007-01-17 19:25:23,367 3146.827(s)
样例输出
hs_10003_m 2007-01-17 19:22:53,318 126.622(s)
hs_10002_m 2007-01-17 19:22:53,315 129.574(s)
hs_10005_m 2007-01-17 19:22:53,318 130.487(s)
hs_10003_p 2007-01-17 19:22:53,318 136.962(s)
hs_10006_m 2007-01-17 19:22:53,318 248.548(s)
hs_10000_p 2007-01-17 19:22:53,315 253.035(s)
hs_10005_p 2007-01-17 19:22:53,318 253.035(s)
hs_10001_p 2007-01-17 19:22:53,315 253.846(s)
hs_10002_p 2007-01-17 19:22:53,315 262.531(s)
hs_10006_p 2007-01-17 19:25:23,367 3146.827(s)
解题思路
- 难点之一是解析日志记录。其中关键是任务开始时间。任务开始时间包含两段,第一段是年月日,第二段是时分秒加上毫秒。
- Python语言的datetime类型适合存储任务开始时间。假如任务开始时间字符串是start_time_str,用datetime.strptime(start_time_str, “%Y-%m-%d %H:%M:%S,%f”)能够转换为精度为微妙的时刻。这里,start_time_str包含年月日、时分秒以及微秒。微秒是从毫秒转换过来的。strptime函数的用法参阅《Python time strptime()方法》一文。
- 根据题目要求,日志排序的做法是,首先按开始时间从前到后对日志记录排序,接着按任务时长从小到大对日志进行排序。这样做,能够保证任务时长一样多时,会按开始时间从前到后排序。
参考答案
下面给出两个版本的参考答案。第一个版本,把日志记录存储为元组,任务名、任务开始时间、任务时长和任务日志信息构成元组的四项内容。第二个版本,把日志记录存储为对象,任务名、任务开始时间、任务时长和任务日志信息是对象的属性。
日志记录存为元组的版本
from datetime import datetime
def set_time_span(log_info):
log = log_info.strip()
task_name, y_m_d, H_M_S_ms, seconds = log.split()
task_name = task_name
start_time_str = y_m_d + ' ' + H_M_S_ms + '000' #加'000'是为了把毫秒变为微秒
start_datetime = datetime.strptime(start_time_str, "%Y-%m-%d %H:%M:%S,%f")
seconds = float(seconds[:-3])
return task_name, start_datetime, seconds, log_info
tasks = []
while True:
line = input()
if line.strip() == '':
break
task = set_time_span(line)
# print(task)
tasks.append(task)
tasks.sort(key=lambda task: task[1])
tasks.sort(key=lambda task: task[2])
for t in tasks:
print(t[3])
日志记录存储为对象的版本
from datetime import datetime
class Task():
def __init__(self, log_info):
self.log_info = log_info
self.set_time_span()
def set_time_span(self):
log = self.log_info.strip()
task_name, y_m_d, H_M_S_ms, seconds = log.split()
self.task_name = task_name
start_time = y_m_d + ' ' + H_M_S_ms # + '000' #加'000'是为了把毫秒变为微妙
self.start_datetime = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S,%f")
self.seconds = float(seconds[:-3])
def __str__(self):
result = 'log_info: ' + self.log_info + '\n'
result += 'task_name: ' + self.task_name + '\n'
result += 'start_time: ' + str(self.start_datetime) + '\n'
result += 'elapsed_time: ' + str(self.seconds) + '\n'
return result
tasks = []
while True:
line = input()
if line.strip() == '':
break
task = Task(line)
# print(task)
tasks.append(task)
tasks.sort(key=lambda task: task.start_datetime)
tasks.sort(key=lambda task: task.seconds)
for t in tasks:
print(t.log_info)
测试用例
- 题目描述给出测试用例,有多条日志记录的开始时间相同而时长不同,有两条日志记录的任务时长相同。
- 两条日志的任务时长相同,日志的开始时间不同,在前面的日志开始时间更晚。
样例输入
hs_10005_p 2007-01-17 19:22:53,318 253.035(s)
hs_10000_p 2007-01-17 19:22:53,315 253.035(s)
样例输出
hs_10000_p 2007-01-17 19:22:53,315 253.035(s)
hs_10005_p 2007-01-17 19:22:53,318 253.035(s)
小结
- 对于本题,会运用datetime类型和strptime函数,代码会更加简洁清晰。
- 本题中,首先对第二排序条件,即任务开始时间,进行排序;接着对第一排序条件,即任务时长,进行排序。这样,能够达成题目要求的顺序。
本文详细解析了一道关于日志排序的算法题,通过对比任务时长和开始时间,使用Python的datetime模块实现精确排序,提供了两种解决方案,一种是基于元组的存储方式,另一种是基于对象的存储方式。
3798

被折叠的 条评论
为什么被折叠?



