【问题标题】:how to efficiently check contiguous ranges in python如何有效地检查python中的连续范围
【发布时间】:2018-05-01 09:32:05
【问题描述】:

根据范围分配等级:

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个检查所以有没有比这种方法做得更好的方法。

【问题讨论】:

  • 创建dictrange 对象(作为键)和等级字符串(作为值)?
  • 范围的上限和下限总是 2^n?
  • 首先扔掉所有最小检查 - 如果会触发它们,则不需要它们
  • if size &lt; 32: do somthing elif size &lt; 64: do something etc. 如果它是 33,则第二个不需要检查 &gt;32 and &lt;=64。如果小于 33,则第一个将触发。这大致将您的陈述减少了 50% - 但使用 max-value:label dict 会更好
  • @PatrickArtner 说了什么。所以你不需要所有那些双重测试。然而,当你确实需要这样的双重测试时,最好写32 &lt; size &lt;= 64而不是size &gt; 32 and size &lt;=64

标签: python python-3.x range


【解决方案1】:

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

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

def getGrade(size):
    grades = (
         (32, 'p4'),
         (64, 'p6'),
        (128, 'p10'),
        ...
    )

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

测试:

>>> getGrade(45)
'p6'
>>> getGrade(100)
'p10'

效率:

如果grades 列表真的很长,您可以获得比扫描每个项目更好的运行时间。由于列表已排序,您可以使用 bisect,通过替换 for 循环:

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

与:

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

步数从 N(grades 的长度)减少(在最坏的情况下)到 log2(N)。

【讨论】:

  • 或者只是return next((grade for s, grade in grades if size &lt;= s), None)?
  • @hiroprotagonist 只有一行长,但就令牌数量而言更长。无论如何,关于代码长度的挑战在这里很愚蠢;关键是“详细”for 更具可读性。 (尽管我是 oneliners 的粉丝)
  • @fferri 我不得不承认:我同意!
【解决方案2】:

蛮力方法很简单

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]

如果列表是指数的,它可能需要空间

【讨论】:

  • 如果范围有20个以上,那就表示最上面的范围是2147483648,绝对是浪费空间!
猜你喜欢
  • 2012-03-13
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多