如何在 Python 中有效地查找区间索引
How to efficiently find indexes of intervals in 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, 317.3, 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, 317.3, 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, number=100_000, globals=globals()))
xgrid = [203.1, 207.2, 304.0, 317.3, 330.7,
344.1, 357.4, 370.8, 400.1, 401.0]
xlist = [310, 320, 335, 399, 402]
print(timeit.timeit(s, number=100_000, globals=globals()))
print(timeit.timeit(s2, number=100_000, globals=globals()))
输出
0.11740579998877365
0.1047545000037644
0.28514970000833273
0.18074260000139475
这表明二分算法对于
较小的列表,并且可能随着较大的列表逐渐变得更好。
你可以试试这个,这样会省时。
xgrid = [304.0, 317.3, 330.7, 344.1, 357.4, 370.8]
xlist = [310, 320, 335]
print([xgrid[i] for i in range(len(xlist)) if xgrid[i] < xlist[i]])
取list中较小的长度,根据自己的问题构造if条件
我有一个网格,网格中有一个值列表。我如何有效地计算与包含它们的网格间隔对应的值的索引列表。这是一个示例代码:
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, 317.3, 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, 317.3, 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, number=100_000, globals=globals()))
xgrid = [203.1, 207.2, 304.0, 317.3, 330.7,
344.1, 357.4, 370.8, 400.1, 401.0]
xlist = [310, 320, 335, 399, 402]
print(timeit.timeit(s, number=100_000, globals=globals()))
print(timeit.timeit(s2, number=100_000, globals=globals()))
输出
0.11740579998877365
0.1047545000037644
0.28514970000833273
0.18074260000139475
这表明二分算法对于 较小的列表,并且可能随着较大的列表逐渐变得更好。
你可以试试这个,这样会省时。
xgrid = [304.0, 317.3, 330.7, 344.1, 357.4, 370.8]
xlist = [310, 320, 335]
print([xgrid[i] for i in range(len(xlist)) if xgrid[i] < xlist[i]])
取list中较小的长度,根据自己的问题构造if条件