去除彼此靠近的二维点

问题描述

我想删除彼此靠近或重复的坐标。

例如

x = [[9,169],[5,164],[340,210],[1020,102],[210,312],[12,150]]

在上面的列表中,第一个和第二个元素彼此靠近。如何在保留第一个元素的同时删除第二个元素?

以下是我尝试过的,

def process(input_list,thresh=(10,10)):
    buffer = input_list.copy()
    n = 0
    prev_cx,prev_cy = 0,0
    for i in range(len(input_list)):
        elem = input_list[i]
        cx,cy = elem
        if n == 0:
            prev_cx,prev_cy = cx,cy
        else:
            ab_cx,ab_cy = abs(prev_cx - cx),abs(prev_cy - cy)
            if ab_cx <= thresh[0] and ab_cy <= thresh[1]:
                del buffer[i]
        n += 1
    return buffer


x = [[9,150]]
processed = process(x)
print(processed)

问题在于它不会递归检查是否有任何其他重复项,因为它只检查相邻坐标。什么是过滤坐标的有效方法

阈值 = (10,10) 的样本输入:

x = [[12,24],12],[100,1020],[20,30],[121,214],[15,12]]

示例输出

x = [[12,214]]

解决方法

你的问题有点含糊,但我的意思是:

  1. 您想比较点的所有组合
  2. 如果组合包含比阈值更近的点
  3. 然后从输入列表的开头进一步删除点

试试这个:

import itertools

def process(input_list,threshold=(10,10)):
    combos = itertools.combinations(input_list,2)
    points_to_remove = [point2
                        for point1,point2 in combos
                        if abs(point1[0]-point2[0])<=threshold[0] and abs(point1[1]-point2[1])<=threshold[1]]
    points_to_keep = [point for point in input_list if point not in points_to_remove]
    return points_to_keep

coords = [[12,24],[5,12],[100,1020],[20,30],[121,214],[15,12]]
print(process(coords))
    
>>> [[12,214]]

这种工作方式是使用 itertools 生成点的所有组合(将点保留在原始顺序中),然后使用阈值创建要删除的点列表。然后它返回不在要删除的点列表中的点列表。

你会注意到我比你多一点。我只是简单地复制了您想要的功能(即 dy 和 dx 但是,如果我使用 AND 语句更改行以删除点 if dy OR dx

所以我要请您重新检查您的示例输出。

顺便说一句,确认分别检查 x 和 y 接近度是否是您真正想要的可能对您有用。所以作为奖励,我还包含了一个使用欧几里得距离的版本:

import itertools
import math

def process(input_list,threshold=100):
    combos = itertools.combinations(input_list,2)
    points_to_remove = [point2 for point1,point2 in combos if math.dist(point1,point2)<=threshold]
    points_to_keep = [point for point in input_list if point not in points_to_remove]
    return points_to_keep

coords = [[12,12]]
print(process(coords))

>>> [[12,214]]

当我使用阈值半径 100 时,此版本适合您的原始样本。

,

我想把它分开一点。当然,这也很棘手,因为您必须修改列表。

def remove_close_neighbors(input_list,thresh,position):
  target_item = input_list[position]
  return [item for i,item in enumerate(input_list) if i == position or not is_close(target_item,item,thresh)]

这将删除所有“重复”(或关闭)点,除了正在考虑的项目。

(然后定义is_close来检查阈值条件)

然后我们可以检查我们的项目:

def process(input_list,thresh):
  pos = 0
  while pos < len(input_list):
    input_list = remove_close_neighbors(input_list,pos)
    pos += 1

这绝不是实现这一目标的最有效方式。这取决于您需要的可扩展性。如果我们在谈论“一亿分”,您将需要研究巧妙的数据结构和算法。我认为 结构可能会很好,“按扇区”对点进行分组,因为这样您就不必一直将每个点与其他点进行比较。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...