如何优化此代码以更快地工作?猜猜它在算法上写得并不完美

时间:2019-06-12 06:55:22

标签: python algorithm optimization

我有一个输入字典。对于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

3 个答案:

答案 0 :(得分:1)

我邀请您使用line_profilerhttps://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。

重复直到结束。