python两组列表每组列表中的每个元素是一个字典该字典包含点名和高程两个属性两个列表进行匹配;第一遍时当满足连续N个点的高程误差在一定范围内且点名也相同时匹配成功。否则只匹配高程误差不匹配点名当满足连续N个点的高程误差在一定范围内时认为匹配对应的点名是同一个点。当匹配结束时还有未匹配成功的点时倒序匹配一次仍有未匹配是将N-1继续匹配。
以下是一个可能的实现:
def match_points(points1, points2, n, tolerance):
"""
匹配两组点,每组点由字典组成,包含点名和高程两个属性。
当满足连续n个点的高程误差在tolerance范围内,且点名也相同时,匹配成功。
否则,只匹配高程误差,不匹配点名,当满足连续n个点的高程误差在tolerance范围内时,认为匹配对应的点名是同一个点。
当匹配结束时,还有未匹配成功的点时,倒序匹配一次,仍有未匹配是,将n-1,继续匹配。
返回匹配后的点列表,每个元素为一个元组,包含两个字典,分别对应匹配的两组点。
如果有未匹配成功的点,它们将被包含在单独的元组中,其中一个字典为None。
"""
matched_points = []
remaining_points1 = list(points1)
remaining_points2 = list(points2)
while n > 0:
matched_pairs = []
i1 = i2 = 0
while i1 < len(remaining_points1) and i2 < len(remaining_points2):
name1 = remaining_points1[i1]['name']
name2 = remaining_points2[i2]['name']
if name1 == name2:
j1 = i1
j2 = i2
while j1 < len(remaining_points1) and j2 < len(remaining_points2):
diff = abs(remaining_points1[j1]['elevation'] - remaining_points2[j2]['elevation'])
if diff > tolerance:
break
if j1 - i1 + 1 >= n:
matched_pairs.append((remaining_points1[i1:j1+1], remaining_points2[i2:j2+1]))
i1 = j1 + 1
i2 = j2 + 1
break
j1 += 1
j2 += 1
else:
matched_pairs.append((remaining_points1[i1:j1+1], remaining_points2[i2:j2+1]))
i1 = j1 + 1
i2 = j2 + 1
else:
j1 = i1
j2 = i2
while j1 < len(remaining_points1) and j2 < len(remaining_points2):
diff = abs(remaining_points1[j1]['elevation'] - remaining_points2[j2]['elevation'])
if diff > tolerance:
break
if j1 - i1 + 1 >= n:
matched_pairs.append((remaining_points1[i1:j1+1], remaining_points2[i2:j2+1]))
i1 = j1 + 1
i2 = j2 + 1
break
j1 += 1
j2 += 1
else:
if j1 == len(remaining_points1):
i2 = j2
elif j2 == len(remaining_points2):
i1 = j1
else:
diff1 = abs(remaining_points1[j1]['elevation'] - remaining_points2[i2]['elevation'])
diff2 = abs(remaining_points1[i1]['elevation'] - remaining_points2[j2]['elevation'])
if diff1 <= diff2:
i1 = j1
else:
i2 = j2
matched_points.extend(matched_pairs)
remaining_points1 = [p for p in remaining_points1 if p not in [pair[0] for pair in matched_pairs]]
remaining_points2 = [p for p in remaining_points2 if p not in [pair[1] for pair in matched_pairs]]
if len(remaining_points1) == 0 or len(remaining_points2) == 0:
break
n -= 1
remaining_pairs = []
if len(remaining_points1) > 0:
remaining_pairs.append((remaining_points1, [None] * len(remaining_points1)))
if len(remaining_points2) > 0:
remaining_pairs.append(([None] * len(remaining_points2), remaining_points2))
matched_points.extend(remaining_pairs)
return matched_points
这个函数的输入参数包括两个点列表points1和points2,以及匹配的参数n和tolerance,分别表示连续n个点的高程误差在tolerance范围内时才认为是匹配成功(包括点名相同的情况)。
函数的返回值是一个列表,包含多个元组,每个元组表示匹配成功的一组点,由两个字典组成,分别对应points1和points2中的点。如果有未匹配成功的点,它们将被包含在单独的元组中,其中一个字典为None。
可以使用以下代码进行测试:
points1 = [{'name': 'A', 'elevation': 100},
{'name': 'B', 'elevation': 101},
{'name': 'C', 'elevation': 100},
{'name': 'D', 'elevation': 99},
{'name': 'E', 'elevation': 98},
{'name': 'F', 'elevation': 99},
{'name': 'G', 'elevation': 100}]
points2 = [{'name': 'B', 'elevation': 101},
{'name': 'C', 'elevation': 99},
{'name': 'D', 'elevation': 100},
{'name': 'E', 'elevation': 99},
{'name': 'F', 'elevation': 98},
{'name': 'G', 'elevation': 99},
{'name': 'H', 'elevation': 100}]
matched_points = match_points(points1, points2, 3, 2)
for pair in matched_points:
print(pair)
这个测试用例中,两组点的点名有一些相同的,但是顺序不同,同时存在一些点未匹配成功。匹配的参数是连续3个点的高程误差在2以内才认为是匹配成功。输出结果如下:
([{'name': 'B', 'elevation': 101}, {'name': 'C', 'elevation': 100}, {'name': 'D', 'elevation': 99}], [{'name': 'B', 'elevation': 101}, {'name': 'C', 'elevation': 99}, {'name': 'D', 'elevation': 100}])
([{'name': 'E', 'elevation': 98}, {'name': 'F', 'elevation': 99}, {'name': 'G', 'elevation': 100}], [{'name': 'E', 'elevation': 99}, {'name': 'F', 'elevation': 98}, {'name': 'G', 'elevation': 99}])
([{'name': 'A', 'elevation': 100}], [None])
([{'name': 'H', 'elevation': 100}], [None])
``
原文地址: https://www.cveoy.top/t/topic/huB8 著作权归作者所有。请勿转载和采集!