Python 仅保留距离值的有效算法

Python 仅保留距离值的有效算法,python,algorithm,Python,Algorithm,我有一个类似以下内容的值列表:[5005018097028088070703502499]我只想将每个数字的第一个实例保持在一定距离内。换句话说,我想得到一个列表:[500809702],因为其他数字与这些数字在一定距离内。所以它将保持500,跳过501,因为它太近,保持809,因为它远离已经选择的值,保持702,等等 以下是我当前的解决方案: vals = ... #the original data result = [] tolerance = 50 for i in vals:

我有一个类似以下内容的值列表:
[5005018097028088070703502499]
我只想将每个数字的第一个实例保持在一定距离内。换句话说,我想得到一个列表:
[500809702]
,因为其他数字与这些数字在一定距离内。所以它将保持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)
vals=#原始数据
结果=[]
公差=50
对于VAL中的i:
如果不是len(np.where(np.abs(结果-i)<公差)[0]):
结果.附加(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]

这应该很快(我在1000000个元素的列表上测试了它,耗时约3秒)。对于列表中的每个元素,您可以通过检查关闭编号集合中的成员身份(即O(1))来检查之前是否已看到关闭值。如果不是,则将其添加到结果中,然后更新关闭编号集

更好的解决方案是使用来自的
SortedSet

在插入元素之前,请检查
irange_键
+-公差
内的所有值。如果没有,则添加此元素


此解决方案应至少比已经建议的
close\u set
方法快一个数量级,并且在内存使用方面也要好一个数量级。此外,如果您需要,它还适用于浮点数和整数。

非常好,谢谢!对于python2,我刚刚将倒数第二行更改为
close\u set.update(范围(e-tolerance,e+tolerance+1))
@jstein123如果要使其与两者兼容,请将该范围包装在
列表()中
我得到了
AttributeError:“SortedSet”对象没有属性“irange_key”
编辑:首先将其转换为SortedKeyList来解决它。谢谢除非我没有正确地实现这一点,否则这似乎比其他发布的解决方案效率更低,因为订单对我的解决方案来说很重要。效率有多低?基于python3.6中的保序dicts,我有一个比@MoxieBall慢2倍的解决方案。我没有发布,因为它比设置的解决方案慢。