2009-07-29 72 views
11

我重构了一个函数,给定一系列隐式定义间隔的端点,检查一个数是否包含在间隔中,然后返回相应的(不相关的,以任何可计算的方式)。 就是现在处理工作的代码是:Python:从间隔映射到值

if p <= 100: 
    return 0 
elif p > 100 and p <= 300: 
    return 1 
elif p > 300 and p <= 500: 
    return 2 
elif p > 500 and p <= 800: 
    return 3 
elif p > 800 and p <= 1000: 
    return 4 
elif p > 1000: 
    return 5 

哪个是IMO相当可怕的,并且缺乏,无论是时间间隔和返回值是硬编码。任何数据结构的使用当然都是可能的。

回答

35
import bisect 
bisect.bisect_left([100,300,500,800,1000], p) 
0

试试沿着线:

d = {(None,100): 0, 
    (100,200): 1, 
    ... 
    (1000, None): 5} 
value = 300 # example value 
for k,v in d.items(): 
    if (k[0] is None or value > k[0]) and (k[1] is None or value <= k[1]): 
     return v 
3

你可以尝试这样的看法:

def check_mapping(p): 
    mapping = [(100, 0), (300, 1), (500, 2)] # Add all your values and returns here 

    for check, value in mapping: 
     if p <= check: 
      return value 

print check_mapping(12) 
print check_mapping(101) 
print check_mapping(303) 

生产:

0 
1 
2 

在Python像往常一样,将有任何更好的方法来做到这一点。

+0

不考虑p> 1000的情况! – stefanw 2009-07-29 09:46:50

+0

这就是为什么我指定:“你可以尝试一下这个” – kjfletch 2009-07-29 10:00:26

+0

最后一句话是讽刺的,考虑到python哲学最好只有一种明显的方式来做某事。 – sykora 2009-07-29 12:11:27

0
def which_interval(endpoints, number): 
    for n, endpoint in enumerate(endpoints): 
     if number <= endpoint: 
      return n 
     previous = endpoint 
    return n + 1 

传递您的终端作为一个列表中endpoints,像这样:

which_interval([100, 300, 500, 800, 1000], 5) 

编辑:

以上是线性搜索。格伦梅纳德的答案将会有更好的表现,因为它使用了二分算法。

0

另一种方式......

def which(lst, p): 
    return len([1 for el in lst if p > el]) 

lst = [100, 300, 500, 800, 1000] 
which(lst, 2) 
which(lst, 101) 
which(lst, 1001) 
3

这的确是相当可怕的。如果没有要求,没有硬编码,它应该被写成这样:

if p <= 100: 
    return 0 
elif p <= 300: 
    return 1 
elif p <= 500: 
    return 2 
elif p <= 800: 
    return 3 
elif p <= 1000: 
    return 4 
else: 
    return 5 

下面是创建查找功能,线性和使用二进制搜索,以满足无hardcodings要求的例子,一对夫妇对这两个表格进行完整性检查:

def make_linear_lookup(keys, values): 
    assert sorted(keys) == keys 
    assert len(values) == len(keys) + 1 
    def f(query): 
     return values[sum(1 for key in keys if query > key)] 
    return f 

import bisect 
def make_bisect_lookup(keys, values): 
    assert sorted(keys) == keys 
    assert len(values) == len(keys) + 1 
    def f(query): 
     return values[bisect.bisect_left(keys, query)] 
    return f