在 Python 中,如何找到排序列表中第一个大于阈值的值的索引?

Posted

技术标签:

【中文标题】在 Python 中,如何找到排序列表中第一个大于阈值的值的索引?【英文标题】:In Python, how do you find the index of the first value greater than a threshold in a sorted list? 【发布时间】:2011-11-09 01:16:24 【问题描述】:

在Python中,如何找到排序列表中第一个大于阈值的值的索引?

我可以想到几种方法(线性搜索,手写二分法,..),但我正在寻找一种干净且合理有效的方法。由于这可能是一个很常见的问题,我相信有经验的 SOers 可以提供帮助!

谢谢!

【问题讨论】:

【参考方案1】:

看看bisect。

import bisect

l = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

bisect.bisect(l, 55) # returns 7

与线性搜索比较:

timeit bisect.bisect(l, 55)
# 375ns


timeit next((i for i,n in enumerate(l) if n > 55), len(l))
# 2.24us


timeit next((l.index(n) for n in l if n > 55), len(l))
# 1.93us

【讨论】:

第二个在没有枚举的情况下会更快,只使用一个简单的循环并返回 list.index()。但离二等分解决方案还很远。 @rplnt - 谢谢,我已将其添加到比较中。你是对的,它比枚举更快。【参考方案2】:

您可能会比使用 itertools 的枚举/生成器方法获得更好的时间;我认为 itertools 为我们所有人的性能贩子提供了更快的底层算法实现。但是 bisect 可能仍然更快。

from itertools import islice, dropwhile

threshold = 5
seq = [1,4,6,9,11]
first_val = islice(dropwhile(lambda x: x<=threshold, seq),0,1)
result = seq.index(first_val)

我想知道这里显示的二等分方法与文档示例中为您的问题列出的方法之间的区别,就成语/速度而言。他们展示了一种查找值的方法,但截断到第一行,它返回索引。我猜想因为它被称为“bisect_right”而不是“bisect”,所以它可能只从一个方向看。鉴于您的列表已排序并且您想要大于,这可能是最大的搜索经济。

from bisect import bisect_right

def find_gt(a, x):
    'Find leftmost value(switching this to index) greater than x'
    return bisect_right(a, x)

有趣的问题。

【讨论】:

【参考方案3】:

最后一个元素的相关索引和值大于阈值

l = [1, 4, 9, 16, 25, 36, 49, 64, 100, 81, 100]
max((x,i) for i, x in enumerate(l) if x > 4)
(100, 10)

【讨论】:

以上是关于在 Python 中,如何找到排序列表中第一个大于阈值的值的索引?的主要内容,如果未能解决你的问题,请参考以下文章

Python二分搜索类函数,用于查找排序列表中大于特定值的第一个数字

在字符串列表中查找字符串中第一个字母的位置(Python 3)

python如何找到列表中极大值

字典排序

第一个Python列表索引大于第二个列表中的元素

python面试题-输入一个由n个大小写字母组成的字符,按Ascii码值从小到大排序,查找字符串中第k个最小Ascii码值的字母