查找表匹配的向量化实现:如何用纯Numpy数组操作替代循环获取样本值的最大下界索引
当然可以!Numpy里有个专门解决这类有序查找问题的函数——np.searchsorted,完全可以替代你写的循环实现,而且效率高得多。
核心思路
你的查找表lookup_table已经是升序排列的,这正好契合searchsorted的使用前提(如果查找表无序,只需要先执行lookup_table.sort()即可)。
np.searchsorted的作用是在有序数组中找到目标值应该插入的位置,以保持数组有序性。我们需要的是「小于等于当前样本值的最大元素的索引」,可以通过设置参数side='right'实现:
- 当
side='right'时,函数会返回第一个大于目标值的元素的位置,将这个位置减1,就是最后一个小于等于目标值的元素的索引——这正是你需要的结果。
改造后的完整代码
直接用一行代码替代原来的last_smallest函数调用即可,完整代码如下:
import numpy as np lookup_table = np.array([4, 6, 7, 8, 10, 12]) samples = np.array([6, 15, 4, 12, 10, 5]) # 用向量化操作替代循环实现的last_smallest result = np.searchsorted(lookup_table, samples, side='right') - 1 for i, value in enumerate(samples): index = result[i] high = lookup_table[index+1] if index < lookup_table.shape[0] - 1 else None print(f'{value} is between {lookup_table[index]} and {high}')
优势说明
- 代码更简洁:不需要手动编写循环和额外函数,一行代码完成核心逻辑
- 性能大幅提升:
searchsorted内部使用二分查找算法,时间复杂度为O(n log m)(n是样本数,m是查找表长度),而原来的循环实现是O(n*m),当样本量或查找表规模较大时,性能差距会非常明显 - 结果完全一致:运行上述代码后,输出和你预期的完全相同:
6 is between 6 and 7 15 is between 12 and None 4 is between 4 and 6 12 is between 12 and None 10 is between 10 and 12 5 is between 4 and 6
内容的提问来源于stack exchange,提问作者mins
相关产品推荐
相关产品推荐

