问题描述
我想删除彼此靠近或重复的坐标。
例如
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]]
解决方法
你的问题有点含糊,但我的意思是:
- 您想比较点的所有组合
- 如果组合包含比阈值更近的点
- 然后从输入列表的开头进一步删除点
试试这个:
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
这绝不是实现这一目标的最有效方式。这取决于您需要的可扩展性。如果我们在谈论“一亿分”,您将需要研究巧妙的数据结构和算法。我认为 树 结构可能会很好,“按扇区”对点进行分组,因为这样您就不必一直将每个点与其他点进行比较。