基于Point类实例列表构建KDTree实现K近邻查询的排序问题求助
你代码里有3个核心错误导致逻辑无法跑通:
- 自定义Point类是普通对象而非序列/映射类型,不能用
point[axis]的下标方式读取属性 depth参数没有作为递归入参传递,每次调用build_index都会重置为0,且depth + 1没有赋值给变量,深度计算完全失效- 递归终止条件错误,数组长度不可能小于0,空数组判断应该写
n == 0
修正方案
- 修改lambda的排序规则,根据axis值对应读取Point的lat、lon属性
- 把depth设为
build_index的可选入参,默认值为0,递归调用时传入depth+1 - 修正终止条件判断
修正后的代码如下:
class KDTreeNN(NearestNeigh): # 把depth作为入参,默认值0,递归时传递 def build_index(self, points: [Point], depth=0): n = len(points) # 修正终止条件:空数组直接返回 if n == 0: return None axis = depth % 2 # 修正排序key,根据axis取对应属性 sorted_points = sorted(points, key = lambda point: point.lat if axis == 0 else point.lon) mid = n // 2 return { 'point': sorted_points[mid], # 递归时传入深度+1 'left': self.build_index(sorted_points[:mid], depth + 1), 'right': self.build_index(sorted_points[mid + 1:], depth + 1) }
如果后续需要扩展维度,也可以提前把Point类的属性名按顺序存在列表里,用getattr动态取值,扩展性更好:
# 提前定义属性顺序,0对应lat,1对应lon AXIS_FIELDS = ['lat', 'lon'] sorted_points = sorted(points, key = lambda point: getattr(point, AXIS_FIELDS[axis]))
内容的提问来源于stack exchange,提问作者vitaminSí
相关产品推荐
相关产品推荐

