删除坐标列表中接近相同的值

我有一个与此类似的值列表:

[[100,100],[101,101],[101,103],[102,103],[104,101],[103,101],[542,121],[943,123]]

我想将接近的值减少到一个单一的值——它可以是一个平均值,但我不依赖于那个特殊性——同时保持独特的值。

因此,从该示例列表中,我想得到类似的信息:

[[101,103],[542,121],[943,123]]

我已经考虑过对值进行除法和四舍五入,去除重复值,然后将它们相乘以达到我的规模,但这会给我的结果

[[100,105],[540,120],[945,125]]

我想保持唯一值的唯一性。


翻过高山走不出你
浏览 160回答 3
3回答

拉莫斯之舞

假设“相似”意味着“在相同中心值的 20 之内”——即所有点的集合,这些点在它们的组合质心的 20 之内。(当然,20 是任意且可配置的。)然后您可以像这样减少列表(假设调用了初始数组data):const threshold = 20;const thresholdSq = threshold ** 2;const groups = data.reduce((map, pair) => {&nbsp; &nbsp; let mini = Infinity, match = null;&nbsp; &nbsp; map.forEach(list => {&nbsp; &nbsp; &nbsp; &nbsp; const avg = list.reduce((sum, point) => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum[0] += point[0];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum[1] += point[1];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return sum;&nbsp; &nbsp; &nbsp; &nbsp; }, [].concat(pair));&nbsp; &nbsp; &nbsp; &nbsp; avg[0] /= 1 + list.length;&nbsp; &nbsp; &nbsp; &nbsp; avg[1] /= 1 + list.length;&nbsp; &nbsp; &nbsp; &nbsp; const distSquared = (avg[0] - pair[0]) ** 2 + (avg[1] - pair[1]) ** 2;&nbsp; &nbsp; &nbsp; &nbsp; if (distSquared < mini && distSquared <= thresholdSq) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mini = distSquared;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = list;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; });&nbsp; &nbsp; if (match) {&nbsp; &nbsp; &nbsp; &nbsp; match.push(pair);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; map.push([pair]);&nbsp; &nbsp; }&nbsp; &nbsp; return map;}, []);const result = groups.map(list => {&nbsp; &nbsp; const sum = list.reduce((acc, v) => {&nbsp; &nbsp; &nbsp; &nbsp; acc[0] += v[0];&nbsp; &nbsp; &nbsp; &nbsp; acc[1] += v[1];&nbsp; &nbsp; &nbsp; &nbsp; return acc;&nbsp; &nbsp; }, [0,0]);&nbsp; &nbsp; sum[0] /= list.length;&nbsp; &nbsp; sum[1] /= list.length;&nbsp; &nbsp; return sum;});对于您的示例数据,结果变为:[[101.83333333333333, 101.5], [542, 121], [943, 123]]这并不完全是您指定的输出,但它确实保留了唯一值并为您提供了其他点组的平均值。

繁花不似锦

一个想法可能是将第一个点分组到桶中,然后你可以对桶做任何你想做的事情,例如平均它们......class Point {&nbsp; constructor(x, y) {&nbsp; &nbsp; this.x = x;&nbsp; &nbsp; this.y = y;&nbsp; &nbsp; this.threshold = 5;&nbsp; }&nbsp; isSimilar(other) {&nbsp; &nbsp; return Math.abs(this.x - other.x) < this.threshold && Math.abs(this.y - other.y) < this.threshold;&nbsp; }&nbsp; avg(other) {&nbsp; &nbsp; &nbsp; return new Point(Math.round((this.x + other.x) / 2), Math.round((this.y + other.y)/2));&nbsp; }}var list = [new Point(100,100),&nbsp; &nbsp; new Point(101,101),&nbsp; &nbsp; new Point(101,103),&nbsp; &nbsp; new Point(102,103),&nbsp; &nbsp; new Point(104,101),&nbsp; &nbsp; new Point(103,101),&nbsp; &nbsp; new Point(542,121),&nbsp; &nbsp; new Point(943,123)];var buckets = []// Group similar points into bucketslist.map(function (p) {&nbsp; &nbsp; var bucket = buckets.find(function(b) { return b[0].isSimilar(p); });&nbsp; &nbsp; if(bucket == undefined) {&nbsp; &nbsp; &nbsp; &nbsp; buckets.push([p]);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; bucket.push(p);&nbsp; &nbsp; }});// Here you could for example average each bucketvar avg = buckets.map(function(b) {&nbsp; &nbsp; return b.reduce(function(a, b) { return a.avg(b); });});console.log(avg);结果:[&nbsp; Point { x: 103, y: 102, threshold: 5 },&nbsp; Point { x: 542, y: 121, threshold: 5 },&nbsp; Point { x: 943, y: 123, threshold: 5 }]注意:使用classECMAScript 2015 引入的...

忽然笑

我已经在 Slack 中提到了这一点,但是如何生成 Voronoi 图,然后找到所有面积小于某个给定值的单元格,并删除 (N-1) 个组成单元格的点?尽管有一个很小的区域,但单元真的很长的边缘情况可能会出现一些问题......
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript