计算排序列表中截止值小于(大于)的元素数量的有效方法

时间:2014-02-03 05:00:44

标签: python

假设我们有一个排序列表:

lst = [1,3,4,89,456,543] # a long one

我们想要做的是找到列表中小于mx的元素数。

易:

n = len([x for x in lst if x < mx])

或与发电机:

n = sum(1 for x in lst if x < mx)

我认为第二种方法应该稍快一些,但是,问题仍然是我们在早期停止时会浏览列表的所有元素。它没有使用列表已排序的事实。

是的,我可以用循环来做到这一点:

s = 0
for x in lst:
    if x >= mx:
        break
    s += 1

但是,我觉得必须有一个更好(更短和/或更快)的方法来做同样的事情,可能有一些发电机或外部模块功能?

2 个答案:

答案 0 :(得分:9)

我们可以通过二进制搜索做得更好,我们可以在bisect模块中轻松实现:

import bisect
n = bisect.bisect_left(lst, mx)

这需要lst长度的对数时间,而早期终止的线性搜索在n中是线性的。这通常会更快。

如果您想使用线性搜索,takewhile中的itertools函数可以提前停止迭代:

import itertools
n = sum(1 for _ in itertools.takewhile(lambda x: x < mx, lst))

答案 1 :(得分:0)

我正在尝试使用二进制搜索来解决:

 #!/usr/bin/python

 lst = range(12, 100)
 mx = 30

 def binary_search(data, target, low, high):
     if low > high:
         return False
     else:
         mid = (low + high) // 2
         if target == data[mid]:
            return mid
         elif target < data[mid]:
            return binary_search(data, target, low, (mid - 1))
         else:
            return binary_search(data, target, mid + 1, high)

 if __name__ == '__main__':
     index = binary_search(lst, mx, 0, len(lst) + 1)
     print 'Count: %d' % len(lst[:index])
     print lst[:index]

输出:

Count : 18
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]