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
我觉得这个代码写得很糟糕,而且问题在于这些区间和返回的值都是写死在代码里的。
当然,你可以使用任何数据结构来解决这个问题。
6 个回答
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
这里有一些创建查找函数的例子,包括线性查找和二分查找,满足不写死代码的要求,并且对这两个表进行了几个合理性检查:
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
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中,总会有更好的方法来实现这个。
56
import bisect
bisect.bisect_left([100,300,500,800,1000], p)
这里是文档链接: bisect