我有一个预定义整数的Python列表:
intvals = [5000, 7500, 10000, 20000, 30000, 40000, 50000]
我需要向下舍入到列表中的下一个更高/更高的值。例如,给定数字8000
,结果应为[7500, 10000]
。对于42000
,它应为[40000, 50000]
。我想知道是否有一种简单的方法可以做到。
我的想法是创建一个具有两个循环的函数 - 一个减少值-1直到它在列表中找到一个循环,另一个将值增加1直到找到更高的匹配。这可行,但也许有更好的解决方案?
答案 0 :(得分:16)
这对bisect.bisect_right()和bisect.bisect_left()来说是完美的。
以下是一些可以展开的示例代码:
import bisect
def get_interval(x):
intvals = [5000, 7500, 10000, 20000, 30000, 40000, 50000]
i = bisect.bisect_right(intvals,x)
return intvals[i-1:i+1]
print get_interval(5500)
"""
>>>
[5000, 7500]
"""
这种技术很快,因为它使用二进制搜索(所以logN而不是N次查找)
答案 1 :(得分:6)
您可以使用bisect模块。您可能需要调整示例以满足您的边界案例需求。
>>> import bisect
>>> def RoundUpDown(rangeList,num):
beg = bisect.bisect_right(rangeList,num)
if rangeList[beg-1] == num: #Handle Perfect Hit Edge Case
return [num,num]
elif not beg: #Left Edge Case
return [None,rangeList[0]]
elif beg == len(rangeList): #Right Edge Case
return [rangeList[-1],None]
else:
return rangeList[beg-1:beg+1]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],41000)
[40000, 50000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],5000)
[5000, 5000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],500)
[None, 5000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],50000)
[50000, 50000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],51000)
[50000, None]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],7500)
[7500, 7500]
>>>
答案 2 :(得分:3)
bisect
专为此类搜索而打造。
>>> intvals[bisect.bisect(intvals, 8000)]
10000
>>> intvals[bisect.bisect(intvals, 42000)]
50000
答案 3 :(得分:0)
将'minDiff'int设置为maxint,将'minIndex'设置为-1。迭代列表并计算索引列表值与目标之间差异的绝对值。如果此值小于minDiff,则将其加载到minDiff并将索引存储在minIndex中。如果该值大于minDiff,则返回minIndex。注 - 假定列表已排序。如果未对列表进行排序,则必须迭代整个列表以确保找到最小差异。
答案 4 :(得分:0)
如果您的间隔不是太大而且您不太担心内存消耗,那么以下解决方案将会很快:
intvals = [5000, 7500, 10000, 20000, 30000, 40000, 50000]
pairs = zip(intvals,intvals[1:])
d = {}
for start,end in pairs:
for i in range(start,end+1):
d[i] = (start,end)
def get_interval(i):
if i in d:
return d[i]
else:
return -1
print get_interval(5500)
"""
>>>
(5000, 7500)
"""
注意我并不担心get_interval(7500)应该返回什么(虽然7500是两个间隔..)但你可以纠正它是你想要的。