如何优化下一个函数,使其工作得更快?该函数必须准备一个列表以放入CSV文件。该列表必须包含从scores中计算的每分钟平均睡眠百分比的值--表格[阶段,时间]的列表,其中的阶段可以是“S”、“R”或“W”,而时间是'%d %H:%M:%S'格式的;如下所示:
scores = [['S', '01 12:11:00'], ['S', '01 12:11:20'], ['W', '01 12:11:40'], ['S', '01 12:12:00'], ...]函数还必须按小时和日对计数值进行分组,因此输出应该如下所示:
quantities = [[1, 12, 11, 0.66], [1, 12, 12, 0.33], [1, 12, 13, 1], ...]from itertools import product
import datetime
def sleep_quantity(scores):
global quantities
quantities = []
for day, hour, minute in product(range(1,4), range(24), range(60)):
sleep = 0
total = 0
quantity = []
for line in scores:
time = datetime.datetime.strptime(line[1], '%d %H:%M:%S')
stage = line[0]
if time.hour == hour and time.day == day and time.minute == minute:
total += 1
if stage == 'S' or stage == 'R':
sleep += 1
if total != 0:
sleep_per_minute = sleep / total
quantity.append(hour)
quantity.append(day)
quantity.append(minute)
quantity.append(sleep_per_minute)
quantities.append(quantity) #for export to CSV
return quantities发布于 2016-03-05 13:05:21
首先,quantities全局功能听起来是不必要的。该值在开始时被清除,并且该值也从函数中返回,不需要关闭全局。
更新quantity的方式可以简化得多,方法是立即追加文字列表,而不是更新变量:
quantities.append([hour, day, minute, sleep / total])现在,另一个快速建议也是在内部for循环中使用析构:
for (stage, time_string) in scores:最后,结果中对小时、日、分钟的排序意味着列表上的常规sort方法不足以以合理的方式对列表进行排序--我建议将其按递减顺序排列,即天、时、分钟。
编辑:在我发布之前已经更新了,但我认为我的假设仍然有效。(不幸的是,对于这个函数为什么会这样做,没有太多的解释。)
然而,现在需要注意的是,设置迭代的方式不如另一种方式有效:product列表是4320元素,而scores列表可能要短得多--听起来应该反过来嵌套它们。
考虑到对代码应该做什么没有任何解释,我将对语义进行一些猜测。现在,我们在一分钟的步骤中迭代三天,检查scores中的任何元素是否匹配,如果匹配,则执行一些操作。对于total,我们会及时积累所有匹配,如果得到匹配,就会追加到quantities列表中。
这意味着,我认为,您正在寻找列表中的所有时间戳,这些时间戳同时发生,然后将时间戳的“类型”相加,并为有匹配的每个时刻追加一个结果。
这可以在排序(时间戳)和累积连续范围方面写得更好:
def sleep_quantity2(scores):
buckets = {}
for stage, time_string in scores:
time = datetime.datetime.strptime(time_string, '%d %H:%M:%S')
stages = buckets.get(time, [0, 0])
buckets[time] = stages
stages[0] += 1
if stage == "R" or stage == "S":
stages[1] += 1
quantities = []
for time, stages in buckets.iteritems():
quantities.append([time.day, time.hour, time.minute, stages[1] / stages[0]])
quantities.sort()
return quantities因此,流程是:将条目累加到桶中,每一刻一个桶,同时更新该桶的数字,然后在结束时遍历所有桶并生成结果列表,并且由于顺序是任意的,因此再次对它们进行排序,使其与前面方法的输出相匹配。
现在,如果您愿意,您仍然可以使用yield来代替累积列表,并在Python2.7中使用xrange而不是range。
哦,运行一个分析器。
作为参考,我最后将它与以下代码进行了比较:
def sleep_quantity1(scores):
quantities = []
for day, hour, minute in product(range(1, 4), range(24), range(60)):
sleep = 0
total = 0
for (stage, time_string) in scores:
time = datetime.datetime.strptime(time_string, '%d %H:%M:%S')
if time.hour == hour and time.day == day and time.minute == minute:
total += 1
if stage == 'S' or stage == 'R':
sleep += 1
if total != 0:
quantities.append([day, hour, minute, sleep / total])
return quantities发布于 2016-03-05 12:09:09
您不需要构建两个列表,一个内部列表和一个外部列表,并将内部列表附加到外部列表中,您可以简化很多,只需yield结果即可。(您可能需要对这个新函数的输出调用list )
def sleep_quantity(scores):
for day, hour, minute in product(range(1,4), range(24), range(60)):
sleep = 0
total = 0
for line in scores:
time = datetime.datetime.strptime(line[1], '%d %H:%M:%S')
stage = line[0]
if time.hour == hour and time.day == day and time.minute == minute:
total += 1
if stage == 'S' or stage == 'R':
sleep += 1
if total != 0:
sleep_per_minute = sleep / total
yield [hour, day, minute, sleep_per_minute]https://codereview.stackexchange.com/questions/121977
复制相似问题