python,找到一个数字所属的范围,范围是从整数列表

时间:2016-02-19 18:00:59

标签: python range

在python中,

有一个整数列表,列表中的每个连续整数形成一个范围。对于给定的数字,我想找到数字所属的范围,并返回范围(或范围的开头)。 E.g。

清单:

[1, 8,   11, 20,   37, 66,   99, 120, ...... ,56000,59001, .....]

号码:

100

结果:

(99,12) OR 99 

数字按递增顺序排列,形成的区域不重叠,列表的大小始终是2的倍数。

列表可能很长,需要检查很多数字。

我试图将整数打包到intervalTree中,并使用search()函数进行检查,但它似乎很慢:

for i in integerList:
    t = IntervalTree(Interval(*iv) for iv in zip(*[iter(annotation_dict.get(i))] * 2))

t.search(theNumber)

是否可以更快或更好地完成?谢谢。

4 个答案:

答案 0 :(得分:1)

由于您的列表已经排序,bisect module是您的朋友。它会为你做O(log(n))搜索。 例如,函数bisect_rightbisect_left非常方便。如果bisect_right返回奇数,则您的数字在一个范围内,该范围的开头是返回值减去1。如果是偶数,那么您的数字在列表的两个不同范围之间。 请参阅下面的示例代码,我直接从结果中减去一个,因此与解释相比,我测试的是反向。

import bisect
loi = [1, 8, 11, 20, 37, 66, 99, 120, 56000, 59001]
idx = bisect.bisect_right(loi,100)-1

if idx%2 == 0:
    print loi[idx]
else:
    print "not in a range"

答案 1 :(得分:0)

您可以使用二进制搜索的修改来提高平均时间复杂度。 1)首先将给定数字与列表的中间元素进行比较。如果它比右半部分的中间更大,则将其与左半部分的中间进行比较。 2)继续第一步,直到得到数字所在的间隔。

答案 2 :(得分:0)

这可能不会更快,但这是一个可能的解决方案(特别是如果您需要避免每次创建IntervalTree的开销)。

def find_range(num, the_list):
    midpt = len(the_list) / 2
    left_list = the_list[0:midpt]
    right_list = the_list[midpt:]
    if num >= left_list[midpt - 1] and num <= right_list[0]:
        rv = (left_list[midpt - 1], right_list[0])
    elif num < left_list[midpt - 1]:
        rv = find_range(num, left_list)
    else:
        rv = find_range(num, right_list)
    return rv

我用一个小样本测试它,它按预期工作,但我会根据IntervalTree解决方案对此解决方案进行基准测试,看看你是否获得/失去了任何东西。

祝你好运!

答案 3 :(得分:0)

您可以使用Python的bisect库,如下所示:

import bisect

loi = [1, 8, 11, 20, 37, 66, 99, 120, 56000, 59001]
index = bisect.bisect_left(loi, 100)

print "({},{})".format(loi[index-1], loi[index])

这将显示以下输出:

(99,120)

它假定值在第一个和最后一个元素内。