如何有效地检查python中的连续范围

how to efficiently check contiguous ranges in python

根据范围分配等级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def getGrade(size):
    grade =''
    if size <= 32:
        grade = 'p4'
    elif size > 32 and size <=64:
        grade = 'p6'
    elif size > 64 and size <= 128:
        grade = 'p10'
    elif size > 128 and size <= 256:
        grade = 'p15'
    elif size > 256 and size <=512:
        grade = 'p20'
    elif size > 512 and size <= 1024:
        grade = 'p30'
    elif size > 1024 and size <= 2048:
        grade = 'p40'
    ......

问题是需要增加20个检查,所以有什么办法比这个方法做得更好。


由于范围是连续的,因此可以避免重复下限。

将所有的范围都放在元组中可以节省一些输入(如果第一个范围不是负无穷大,请考虑在所有其他范围之前添加元组(0, None)

1
2
3
4
5
6
7
8
9
10
11
def getGrade(size):
    grades = (
         (32, 'p4'),
         (64, 'p6'),
        (128, 'p10'),
        ...
    )

    for maxVal, grade in grades:
        if size <= maxVal:
            return grade

测试:

1
2
3
4
>>> getGrade(45)
'p6'
>>> getGrade(100)
'p10'

效率:

如果grades列表真的很长,那么可以实现比扫描每个项目更好的运行时。由于对列表进行了排序,因此可以使用bisect,方法是替换for循环:

1
2
3
    for maxVal, grade in grades:
        if size <= maxVal:
            return grade

用:

1
2
3
    index = bisect.bisect(grades, (size, ))
    if index < len(grades):
        return grades[index][1]

步骤数(最坏情况下)从n(grades的长度)减少到log2(sub>(n)。


蛮力的方法很简单

1
2
3
4
5
all_grades = [i for i in chain(repeat('p4',32),repeat('p6',64-32) and so on)]

then you can get grade as

grade = all_grades[size-1]

如果列表是指数的,则可能需要空格