我有一个输入字典。对于dict中的每个键,值是一个整数列表。此列表中的每个整数都是以秒为单位的时间记录,显示了何时发生某些操作。我的目标是为每个键找出1分钟内发生的最大操作次数。
我已经编写了解决此问题的代码,但执行速度太慢。它没有通过测试(不是我的测试,我不知道它包含什么输入)。我已经迭代完善了代码,但是它仍然太慢,因此我认为我使用的算法不好。您能帮我找到一个好的吗?您只能使用标准库!
php artisan clear-compiled
composer dump-autoload
php artisan cache:clear
php artisan config:clear
php artisan view:clear
样本输入: seconds_for_exc = {“ A”:[34201.034,34255.000,34255.554,34261.034], “ B”:[34255.556,34261.033]}
更新 正确的代码应如下所示:
trades_for_exc = {}
# largest_for_exc is an output dict
largest_for_exc = {}
# seconds_for_exc is an unput dict
for key, value in seconds_for_exc.items():
val_len = len(value)
largest = 0
# iterate through all values in some list
for i in range(0, val_len):
new_largest = 1
i_in_seconds = value[i]
# iterate through all values starting from current to compare time
for trades in value[i+1:]:
if trades - i_in_seconds < 60.0:
new_largest += 1
else:
break
if new_largest > largest:
largest = new_largest
largest_for_exc[key] = largest
答案 0 :(得分:1)
我邀请您使用line_profiler
(https://github.com/rkern/line_profiler)来查看哪一行最耗时。
通常不建议将多个循环串联在一起,因为这会增加有时是多余的操作数量。
一个一般建议是在np.array
中转换您的整数列表(包含在词典中)。大量的数据结构需要速度,并且比列表要快。
它将帮助您向量化循环并提高代码性能。检查此链接:https://hackernoon.com/speeding-up-your-code-2-vectorizing-the-loops-with-numpy-e380e939bed3
答案 1 :(得分:0)
这是一个解决方案,我希望它会更快。主要思想是将时间用作索引而不是值,并使用pandas
.rolling()
方法对每分钟(有事件的地方)的事件进行计数,然后取最大值:
import pandas as pd
trades_for_exc = {'a': [155, 200, 300], 'b':[10, 80, 120, 130], 'c': [0]}
max_actions_in_one_minute = {k:
pd.Series(
index=pd.to_datetime(v,unit='s'),
data=1
).rolling('60s').count().max()
for k,v in trades_for_exc.items()}
[添加后编辑,仅使用标准库]: 这可以通过列表理解来完成-看看它是否更快:
max_actions_in_one_minute = {k: max([len([y for y in v if y>=x and y<=x+60]) for x in v])
for k, v in trades_for_exc.items()}
答案 2 :(得分:0)
算法的运行时间是每个列表中项目的二次数,因此,只要列表变大,算法的运行速度就会变慢。
您可以使用这种方法,它具有线性运行时: 使用两个索引,一个用于间隔的开始,一个用于结束。推进第二个索引并记录最大跨度,直到时间差> = 60。然后推进起始索引,直到差异再次<60。
重复直到结束。