仅保留远距离值的高效算法

时间:2018-07-19 18:45:13

标签: python algorithm

我有一个值列表,看起来可能像这样:[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万个元素)。是否有解决此问题的有效方法?谢谢!

编辑:为澄清起见,我需要保留每个组的 first 元素,而不是最小的元素(即,在以上示例中,[499, 702, 807]不会是有效的结果),因此排序可能没有太大帮助。

2 个答案:

答案 0 :(得分:4)

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))中的成员资格来检查以前是否已看到闭合值。如果不是,则将其添加到结果中,然后更新收盘价集。

答案 1 :(得分:1)

更好的解决方案是使用http://www.grantjenks.com/docs/sortedcontainers/index.html中的SortedSet

在插入元素之前,请检查irange_key中的所有值+- tolerance。如果没有任何内容,则添加此元素。

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