基于距离生成X、Y坐标的算法推荐(NodeJS+Mongoose)
位置生成算法实现方案(NodeJS + Mongoose)
现有Locations数据示例
{ x: 0, y: 0 }, { x: 2, y: 1 }, { x: -1, y: -2 }
核心需求
- 新生成的位置需距离原点(0,0)最近
- 新位置必须满足:某一轴与原点的差值为2,另一轴差值为1(例如
{x:2,y:1}、{x:-2,y:1}等所有符合此规则的坐标) - 距离计算采用勾股定理,公式如下:
Math.sqrt(Math.pow(x - x1, 2) + Math.pow(y - y1, 2))
推荐算法(避免全量遍历)
步骤1:预定义所有符合规则的候选坐标
根据需求,满足条件的坐标共有8种可能,直接枚举即可——这些点到原点的距离均为√5(约2.236),是符合规则的最小距离,无需额外排序:
const candidatePoints = [ {x: 2, y: 1}, {x: 2, y: -1}, {x: -2, y: 1}, {x: -2, y: -1}, {x: 1, y: 2}, {x: 1, y: -2}, {x: -1, y: 2}, {x: -1, y: -2} ];
步骤2:用Mongoose查询已占用的候选点
直接在数据库层面过滤已存在的符合规则的坐标,避免全量遍历集合:
const existingPoints = await Location.find({ $or: candidatePoints.map(point => ({x: point.x, y: point.y})) }).select('x y');
步骤3:筛选第一个未被占用的点
将已存在的坐标转为字符串存入Set,实现O(1)的查找效率,遍历候选数组返回第一个未被占用的点:
const existingSet = new Set(existingPoints.map(p => `${p.x},${p.y}`)); const newPoint = candidatePoints.find(point => { const key = `${point.x},${point.y}`; return !existingSet.has(key); });
若所有候选点都被占用,可根据业务需求扩展逻辑(比如生成距离次近的符合规则的点,如某轴差值为3、另一轴为1等)。
完整代码示例
const mongoose = require('mongoose'); // 假设Location Schema定义如下 const locationSchema = new mongoose.Schema({ x: Number, y: Number }); const Location = mongoose.model('Location', locationSchema); async function generateNewLocation() { // 预定义符合规则的候选点 const candidatePoints = [ {x: 2, y: 1}, {x: 2, y: -1}, {x: -2, y: 1}, {x: -2, y: -1}, {x: 1, y: 2}, {x: 1, y: -2}, {x: -1, y: 2}, {x: -1, y: -2} ]; // 查询已存在的候选点 const existingPoints = await Location.find({ $or: candidatePoints.map(point => ({x: point.x, y: point.y})) }).select('x y'); // 转Set快速判断占用状态 const existingSet = new Set(existingPoints.map(p => `${p.x},${p.y}`)); // 筛选第一个可用点 const newPoint = candidatePoints.find(point => { const key = `${point.x},${point.y}`; return !existingSet.has(key); }); if (newPoint) { await Location.create(newPoint); return newPoint; } else { throw new Error('所有符合最近距离规则的位置已被占用'); } }
内容的提问来源于stack exchange,提问作者vy.pham
相关产品推荐
相关产品推荐

