简体   繁体   English

如何提高我的选择过程的速度,python

[英]How to improve the speed of my selection process, python

Edit: Due to errors in my code i updated with my oldest, but working code 编辑:由于我的代码中的错误,我用我最老但工作的代码更新

I get a list of speed recordings from a database, and I want to find the max speed in that list. 我从数据库中获得了一个速度记录列表,我想找到该列表中的最大速度。 Sounds easy enough, but I got some requirements for any max speed to count: 听起来很容易,但我对任何最大速度都有一些要求:

If the max speed is over a certain level, it has to have more than a certain number of records to be recognized as maximum speed. 如果最大速度超过一定水平,则必须将超过一定数量的记录识别为最大速度。 The reason for this logic is that I want the max speed under normal conditions, not just an error or one time occurrence. 这种逻辑的原因是我想要在正常条件下的最大速度,而不仅仅是错误或一次出现。 I also have a constraint that a speed has to be over a certain limit to be counted, for the same reason. 出于同样的原因,我还有一个约束,即速度必须超过一定的限制才能计算。

Here is the example on a speed array: 以下是速度数组的示例:

v = [8.0, 1.3, 0.7, 0.8, 0.9, 1.1, 14.9, 14.0, 14.1, 14.2, 14.3, 13.8, 13.9, 13.7, 13.6, 13.5, 13.4, 15.7, 15.8, 15.0, 15.3, 15.4, 15.5, 15.6, 15.2, 12.8, 12.7, 12.6, 8.7, 8.8, 8.6, 9.0, 8.5, 8.4, 8.3, 0.1, 0.0, 16.4, 16.5, 16.7, 16.8, 17.0, 17.1, 17.8, 17.7, 17.6, 17.4, 17.5, 17.3, 17.9, 18.2, 18.3, 18.1, 18.0, 18.4, 18.5, 18.6, 19.0, 19.1, 18.9, 19.2, 19.3, 19.9, 20.1, 19.8, 20.0, 19.7, 19.6, 19.5, 20.2, 20.3, 18.7, 18.8, 17.2, 16.9, 11.5, 11.2, 11.3, 11.4, 7.1, 12.9, 14.4, 13.1, 13.2, 12.5, 12.1, 12.2, 13.0, 0.2, 3.6, 7.4, 4.6, 4.5, 4.3, 4.0, 9.4, 9.6, 9.7, 5.8, 5.7, 7.3, 2.1, 0.4, 0.3, 16.1, 11.9, 12.0, 11.7, 11.8, 10.0, 10.1, 9.8, 15.1, 14.7, 14.8, 10.2, 10.3, 1.2, 9.9, 1.9, 3.4, 14.6, 0.6, 5.1, 5.2, 7.5, 19.4, 10.7, 10.8, 10.9, 0.5, 16.3, 16.2, 16.0, 16.6, 12.4, 11.0, 1.7, 1.6, 2.4, 11.6, 3.9, 3.8, 14.5, 11.1]

This is my code to find what I define as the true maximum speed: 这是我的代码,以找到我定义为真正的最大速度:

from collections import Counter
while max(speeds)>30:
    speeds.remove(max(speeds))
nwsp = []
for s in speeds:
    nwsp.append(np.floor(s))
count = Counter(nwsp)
while speeds and max(speeds)>14 and count[np.floor(max(speeds))]<10:
    speeds.remove(max(speeds))
while speeds and max(speeds)<5:
    speeds.remove(max(speeds))
if speeds:
    print max(speeds)
    return max(speeds)
else:
    return False

Result with v as shown over: 19.9 结果如图所示:19.9

The reason that i make the nwsp is that it doesn't matter for me if f.ex 19.6 is only found 9 times - if any number inside the same integer, f.ex 19.7 is found 3 times as well, then 19.6 will be valid. 我做nwsp的原因是,如果f.ex 19.6只被发现9次对我来说无关紧要 - 如果在同一个整数内有任何数字,f.ex 19.7也被找到3次,那么19.6将是有效。

How can I rewrite/optimize this code so the selection process is quicker? 如何重写/优化此代码以便选择过程更快? I already removed the max(speeds) and instead sorted the list and referenced the largest element using speeds[-1]. 我已经删除了max(速度),而是对列表进行了排序,并使用velocity [-1]引用了最大的元素。

Sorry for not adding any unit to my speeds. 很抱歉没有为我的速度添加任何单位。

Your code is just slow because you call max and remove over and over and over again and each of those calls costs time proportional to the length of the list. 您的代码速度很慢,因为您调用max并一遍又一遍地remove ,并且每个调用都需要与列表长度成比例的时间。 Any reasonable solution will be much faster. 任何合理的解决方案都会快得多。

If you know that False can't happen, then this suffices: 如果您知道False不会发生,那么这就足够了:

speeds = [8.0, 1.3, 0.7, 0.8, 0.9, 1.1, 14.9, 14.0, 14.1, 14.2, 14.3, 13.8, 13.9, 13.7, 13.6, 13.5, 13.4, 15.7, 15.8, 15.0, 15.3, 15.4, 15.5, 15.6, 15.2, 12.8, 12.7, 12.6, 8.7, 8.8, 8.6, 9.0, 8.5, 8.4, 8.3, 0.1, 0.0, 16.4, 16.5, 16.7, 16.8, 17.0, 17.1, 17.8, 17.7, 17.6, 17.4, 17.5, 17.3, 17.9, 18.2, 18.3, 18.1, 18.0, 18.4, 18.5, 18.6, 19.0, 19.1, 18.9, 19.2, 19.3, 19.9, 20.1, 19.8, 20.0, 19.7, 19.6, 19.5, 20.2, 20.3, 18.7, 18.8, 17.2, 16.9, 11.5, 11.2, 11.3, 11.4, 7.1, 12.9, 14.4, 13.1, 13.2, 12.5, 12.1, 12.2, 13.0, 0.2, 3.6, 7.4, 4.6, 4.5, 4.3, 4.0, 9.4, 9.6, 9.7, 5.8, 5.7, 7.3, 2.1, 0.4, 0.3, 16.1, 11.9, 12.0, 11.7, 11.8, 10.0, 10.1, 9.8, 15.1, 14.7, 14.8, 10.2, 10.3, 1.2, 9.9, 1.9, 3.4, 14.6, 0.6, 5.1, 5.2, 7.5, 19.4, 10.7, 10.8, 10.9, 0.5, 16.3, 16.2, 16.0, 16.6, 12.4, 11.0, 1.7, 1.6, 2.4, 11.6, 3.9, 3.8, 14.5, 11.1]

from collections import Counter
count = Counter(map(int, speeds))
print max(s for s in speeds
          if 5 <= s <= 30 and (s <= 14 or count[int(s)] >= 10))

If the False case can happen, this would be one way: 如果可能发生False情况,这将是一种方式:

speeds = [8.0, 1.3, 0.7, 0.8, 0.9, 1.1, 14.9, 14.0, 14.1, 14.2, 14.3, 13.8, 13.9, 13.7, 13.6, 13.5, 13.4, 15.7, 15.8, 15.0, 15.3, 15.4, 15.5, 15.6, 15.2, 12.8, 12.7, 12.6, 8.7, 8.8, 8.6, 9.0, 8.5, 8.4, 8.3, 0.1, 0.0, 16.4, 16.5, 16.7, 16.8, 17.0, 17.1, 17.8, 17.7, 17.6, 17.4, 17.5, 17.3, 17.9, 18.2, 18.3, 18.1, 18.0, 18.4, 18.5, 18.6, 19.0, 19.1, 18.9, 19.2, 19.3, 19.9, 20.1, 19.8, 20.0, 19.7, 19.6, 19.5, 20.2, 20.3, 18.7, 18.8, 17.2, 16.9, 11.5, 11.2, 11.3, 11.4, 7.1, 12.9, 14.4, 13.1, 13.2, 12.5, 12.1, 12.2, 13.0, 0.2, 3.6, 7.4, 4.6, 4.5, 4.3, 4.0, 9.4, 9.6, 9.7, 5.8, 5.7, 7.3, 2.1, 0.4, 0.3, 16.1, 11.9, 12.0, 11.7, 11.8, 10.0, 10.1, 9.8, 15.1, 14.7, 14.8, 10.2, 10.3, 1.2, 9.9, 1.9, 3.4, 14.6, 0.6, 5.1, 5.2, 7.5, 19.4, 10.7, 10.8, 10.9, 0.5, 16.3, 16.2, 16.0, 16.6, 12.4, 11.0, 1.7, 1.6, 2.4, 11.6, 3.9, 3.8, 14.5, 11.1]

from collections import Counter
count = Counter(map(int, speeds))
valids = [s for s in speeds
         if 5 <= s <= 30 and (s <= 14 or count[int(s)] >= 10)]
print max(valids) if valids else False

Or sort and use next , which can take your False as default: 或者排序并使用next ,默认情况下可以使用False

speeds = [8.0, 1.3, 0.7, 0.8, 0.9, 1.1, 14.9, 14.0, 14.1, 14.2, 14.3, 13.8, 13.9, 13.7, 13.6, 13.5, 13.4, 15.7, 15.8, 15.0, 15.3, 15.4, 15.5, 15.6, 15.2, 12.8, 12.7, 12.6, 8.7, 8.8, 8.6, 9.0, 8.5, 8.4, 8.3, 0.1, 0.0, 16.4, 16.5, 16.7, 16.8, 17.0, 17.1, 17.8, 17.7, 17.6, 17.4, 17.5, 17.3, 17.9, 18.2, 18.3, 18.1, 18.0, 18.4, 18.5, 18.6, 19.0, 19.1, 18.9, 19.2, 19.3, 19.9, 20.1, 19.8, 20.0, 19.7, 19.6, 19.5, 20.2, 20.3, 18.7, 18.8, 17.2, 16.9, 11.5, 11.2, 11.3, 11.4, 7.1, 12.9, 14.4, 13.1, 13.2, 12.5, 12.1, 12.2, 13.0, 0.2, 3.6, 7.4, 4.6, 4.5, 4.3, 4.0, 9.4, 9.6, 9.7, 5.8, 5.7, 7.3, 2.1, 0.4, 0.3, 16.1, 11.9, 12.0, 11.7, 11.8, 10.0, 10.1, 9.8, 15.1, 14.7, 14.8, 10.2, 10.3, 1.2, 9.9, 1.9, 3.4, 14.6, 0.6, 5.1, 5.2, 7.5, 19.4, 10.7, 10.8, 10.9, 0.5, 16.3, 16.2, 16.0, 16.6, 12.4, 11.0, 1.7, 1.6, 2.4, 11.6, 3.9, 3.8, 14.5, 11.1]

count = Counter(map(int, speeds))
print next((s for s in reversed(sorted(speeds))
            if 5 <= s <= 30 and (s <= 14 or count[int(s)] >= 10)),
           False)

Instead of Counter , you could also use groupby : 而不是Counter ,你也可以使用groupby

speeds = [8.0, 1.3, 0.7, 0.8, 0.9, 1.1, 14.9, 14.0, 14.1, 14.2, 14.3, 13.8, 13.9, 13.7, 13.6, 13.5, 13.4, 15.7, 15.8, 15.0, 15.3, 15.4, 15.5, 15.6, 15.2, 12.8, 12.7, 12.6, 8.7, 8.8, 8.6, 9.0, 8.5, 8.4, 8.3, 0.1, 0.0, 16.4, 16.5, 16.7, 16.8, 17.0, 17.1, 17.8, 17.7, 17.6, 17.4, 17.5, 17.3, 17.9, 18.2, 18.3, 18.1, 18.0, 18.4, 18.5, 18.6, 19.0, 19.1, 18.9, 19.2, 19.3, 19.9, 20.1, 19.8, 20.0, 19.7, 19.6, 19.5, 20.2, 20.3, 18.7, 18.8, 17.2, 16.9, 11.5, 11.2, 11.3, 11.4, 7.1, 12.9, 14.4, 13.1, 13.2, 12.5, 12.1, 12.2, 13.0, 0.2, 3.6, 7.4, 4.6, 4.5, 4.3, 4.0, 9.4, 9.6, 9.7, 5.8, 5.7, 7.3, 2.1, 0.4, 0.3, 16.1, 11.9, 12.0, 11.7, 11.8, 10.0, 10.1, 9.8, 15.1, 14.7, 14.8, 10.2, 10.3, 1.2, 9.9, 1.9, 3.4, 14.6, 0.6, 5.1, 5.2, 7.5, 19.4, 10.7, 10.8, 10.9, 0.5, 16.3, 16.2, 16.0, 16.6, 12.4, 11.0, 1.7, 1.6, 2.4, 11.6, 3.9, 3.8, 14.5, 11.1]

from itertools import *
groups = (list(group) for _, group in groupby(reversed(sorted(speeds)), int))
print next((s[0] for s in groups
            if 5 <= s[0] <= 30 and (s[0] <= 14 or len(s) >= 10)),
           False)

Just in case all of these look odd to you, here's one close to your original. 以防所有这些看起来很奇怪,这里有一个接近你原来的。 Just looking at the speeds from fastest to slowest and returning the first that matches the requirements: 只需查看从最快到最慢的速度并返回符合要求的第一个:

def f(speeds):
    count = Counter(map(int, speeds))
    for speed in reversed(sorted(speeds)):
        if 5 <= speed <= 30 and (speed <= 14 or count[int(speed)] >= 10):
            return speed
    return False

Btw, your definition of "the true maximum speed" seems rather odd to me. 顺便说一下,你对“真正的最大速度”的定义对我来说似乎很奇怪。 How about just looking at a certain percentile? 只看某个百分点怎么样? Maybe like this: 也许是这样的:

print sorted(speeds)[len(speeds) * 9 // 10]

I'm not sure if this is faster, but it is shorter, and I think it achieves your requirements. 我不确定这是否更快,但它更短,我认为它可以满足您的要求。 It uses Counter . 它使用Counter

from collections import Counter
import math

def valid(item):
  speed,count = item
  return speed <= 30 and (speed <= 13 or count >= 10)

speeds = [4,3,1,3,4,5,6,7,14,16,18,19,20,34,5,4,3,2,12,58,14,14,14]

speeds = map(math.floor,speeds)
counts = Counter(speeds)
max_valid_speed = max(filter(valid,counts.items()))

Result: max_valid_speed == (12,1) 结果: max_valid_speed == (12,1)

Using your sort idea we can start at the end of the list at the numbers less than 30, returning on the first number that matched the criteria or returning False: 使用您的排序想法,我们可以从列表末尾开始,小于30的数字,返回匹配条件的第一个数字或返回False:

from collections import Counter

def f(speeds):
    # get speeds that satisfy the range
    rev = [speed for speed in speeds if 5 <= speed < 30]
    rev.sort(reverse=True)
    c = Counter((int(v) for v in rev))
    for speed in rev:
        # will hit highest numbers first
        # so return first that matches
        if speed > 14 and c[int(speed)] > 9 or speed < 15:
            return speed
    # we did not find any speed that matched our requirement
    return False

Output for your list v: 列表输出v:

In [70]: f(v)
Out[70]: 19.9

Without sorting you could use a dict, depending on your what your data is like will decide which is best, it will work for all cases including an empty list: 如果没有排序,您可以使用dict,根据您的数据将决定哪个最好,它将适用于所有情况,包括空列表:

 def f_dict(speeds):
    d = defaultdict(lambda: defaultdict(lambda: 0, {}))
    for speed in speeds:
        key = int(speed)
        d[key]["count"] += 1
        if speed > d[key]["speed"]:
            d[key]["speed"] = speed
    filt = max(filter(lambda x: (15 <= x[0] < 30 and
                                 x[1]["count"] > 9 or x[0] < 15), d.items()), default=False)
    return filt[1]["speed"] if filt else False

Output: 输出:

In [95]: f_dict(v)
Out[95]: 19.9

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM