python - 仅保留远距离值的有效算法
问题描述
我有一个可能看起来像这样的值列表:[500,501,809,702,808,807,703,502,499]
并且我只想将每个数字的第一个实例保持在一定距离内。换句话说,我想得到这个列表:[500,809,702]
因为其他数字与这些数字有一定的距离。所以它会保留 500,跳过 501 因为它太近了,保留 809 因为它远离已经选择的值,保留 702,等等。
这是我目前的解决方案:
vals = ... #the original data
result = []
tolerance = 50
for i in vals:
if not len(np.where(np.abs(result - i) < tolerance)[0]):
results.append(i)
这很好用,但对于我的目的来说太慢了(我正在处理列表中的 240 万个元素)。这个问题有有效的解决方案吗?谢谢!
编辑:为了澄清,我需要保留每个组的第一个元素,而不是最小的元素(即[499, 702, 807]
在上面的示例中不是有效的结果),因此对其进行排序可能没有太大帮助。
解决方案
vals = [500,501,809,702,808,807,703,502,499]
close_set = set()
tolerance = 5
result = []
for e in vals:
if e in close_set:
continue
else:
result.append(e)
close_set.update([*range(e-tolerance, e+tolerance+1)])
print(result) # [500, 809, 702]
这应该很快(我在 1,000,000 个元素的列表上对其进行了测试,大约需要 3 秒)。对于列表中的每个元素,您可以通过检查接近数字集合中的成员资格来检查是否以前看到过接近值,即 O(1)。如果不是,则将其添加到结果中,然后更新关闭数字集。
推荐阅读
- python - 为什么我的方法只影响方法内部的类?
- deep-learning - 序列数据是否会使模型过度拟合训练数据?
- c++ - STL priority_queue push 函数添加一个完整的链表(向量
& 列表),而不是一个元素 - python - 从数据框列中的列表中查找元素(列的类型是列表)
- ruby - 如何正确销毁具有关系的 Mongoid 嵌入对象?
- python - Django View 仅返回 QuerySet 一部分的数据
- javascript - 从 api 服务器获取数据后,我无法从 app.js 更改 h3
- python - 当我有自己的传真机时,如何使用 python 发送传真?
- javascript - 无法使用 Vue 在 Firebase 中创建 ref 用户/注册
- c++ - 矩阵类模板,不同类型矩阵的乘法或加法