Python入门习题(96)——OpenJudge百练习题:日志排序

本文详细解析了一道关于日志排序的算法题,通过对比任务时长和开始时间,使用Python的datetime模块实现精确排序,提供了两种解决方案,一种是基于元组的存储方式,另一种是基于对象的存储方式。

题目描述

来源
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)

解题思路

  1. 难点之一是解析日志记录。其中关键是任务开始时间。任务开始时间包含两段,第一段是年月日,第二段是时分秒加上毫秒。
  2. Python语言的datetime类型适合存储任务开始时间。假如任务开始时间字符串是start_time_str,用datetime.strptime(start_time_str, “%Y-%m-%d %H:%M:%S,%f”)能够转换为精度为微妙的时刻。这里,start_time_str包含年月日、时分秒以及微秒。微秒是从毫秒转换过来的。strptime函数的用法参阅《Python time strptime()方法》一文。
  3. 根据题目要求,日志排序的做法是,首先按开始时间从前到后对日志记录排序,接着按任务时长从小到大对日志进行排序。这样做,能够保证任务时长一样多时,会按开始时间从前到后排序。

参考答案

下面给出两个版本的参考答案。第一个版本,把日志记录存储为元组,任务名、任务开始时间、任务时长和任务日志信息构成元组的四项内容。第二个版本,把日志记录存储为对象,任务名、任务开始时间、任务时长和任务日志信息是对象的属性。

日志记录存为元组的版本
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)

测试用例

  1. 题目描述给出测试用例,有多条日志记录的开始时间相同而时长不同,有两条日志记录的任务时长相同。
  2. 两条日志的任务时长相同,日志的开始时间不同,在前面的日志开始时间更晚。
    样例输入
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)

小结

  1. 对于本题,会运用datetime类型和strptime函数,代码会更加简洁清晰。
  2. 本题中,首先对第二排序条件,即任务开始时间,进行排序;接着对第一排序条件,即任务时长,进行排序。这样,能够达成题目要求的顺序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值