如何在 Python 中有效地找到区间的索引

问题描述

我有一个网格,以及一个位于网格中的值列表。如何有效地计算与包含它们的网格间隔相对应的值的索引列表。这是一个示例代码

xgrid = [304.0,317.3,330.7,344.1,357.4,370.8]
xlist = [310,320,360]

output = []
for x in xlist:
    for xi in xgrid:
        if (xi < x):
            xindex = xi
    output.append(xindex)

print(output)

此示例的预期输出为 [304.0,357.4]。

xgrid 的大小为 50 左右,但 xlist 可能更大,包含 100-200 个值。

解决方法

Python 标准库提供了 bisect,可用于进行搜索 给你:

import bisect

xgrid = [304.0,317.3,330.7,344.1,357.4,370.8]
xlist = [310,320,335]

def find_lt(a,x):
    'Find rightmost value less than x'
    i = bisect.bisect_left(a,x)
    if i:
        return a[i-1]
    raise ValueError

print([find_lt(xgrid,x) for x in xlist])
# Output: [304.0,330.7]

关于速度,我尝试了以下(附加到上面的代码):

import timeit

s = '''\
output = []
for x in xlist:
    for xi in xgrid:
        if (xi < x):
            xindex = xi
    output.append(xindex)
'''
s2 = '''\
output = [find_lt(xgrid,x) for x in xlist]
'''
print(timeit.timeit(s,number=100_000,globals=globals()))
print(timeit.timeit(s2,globals=globals()))

xgrid = [203.1,207.2,304.0,370.8,400.1,401.0]
xlist = [310,335,399,402]
print(timeit.timeit(s,globals=globals()))

输出

0.11740579998877365
0.1047545000037644
0.28514970000833273
0.18074260000139475

这表明二分算法稍微快一点 小列表,大列表可能会逐渐变得更好。

,

你可以试试这个,这样会节省时间。

xgrid = [304.0,335]

print([xgrid[i] for i in range(len(xlist)) if xgrid[i] < xlist[i]])

取较小的列表长度,您可以根据您的问题构造if条件。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...