在Javascript中,如何根据点到参考点的距离对点数组进行排序?
我有一个工作代码,在这里:在Javascript中,如何根据点到参考点的距离对点数组进行排序?,javascript,arrays,sorting,Javascript,Arrays,Sorting,我有一个工作代码,在这里: function simpleDist(pointA, pointB) { var x = pointA.x - pointB.x, y = pointA.y - pointB.y; return Math.sqrt(x*x + y*y); } function sortByDist(pointRef, pointArray) { var distancePairs = [], output = []; for(var p
function simpleDist(pointA, pointB) {
var x = pointA.x - pointB.x,
y = pointA.y - pointB.y;
return Math.sqrt(x*x + y*y);
}
function sortByDist(pointRef, pointArray) {
var distancePairs = [],
output = [];
for(var p in pointArray) {
var pointComp = pointArray[p];
distancePairs.push([simpleDist(pointRef,pointComp), p]);
}
distancePairs.sort(function(a,b) {
return a[0]-b[0];
});
for(var p in distancePairs) {
var pair = distancePairs[p];
output.push(pointArray[pair[1]]);
}
return output;
}
这对我所做的工作是有效的。但是,我想知道是否有一种更简单的方法可以使用Array.sort来完成。我已经看过了Array.sort的一些解释,它似乎需要接受3个函数来执行我需要的操作,而不需要这里的解决方法。不过我觉得我只是有点麻木。您能找到使此功能更快或更简化的方法吗?更新
下面是如何修改我的代码以使用memoize decorator。
它的好处是,记忆化不太依赖于比较对象的实现。
我不确定JSON.stringify的速度有多快,但看起来已经足够快了,毕竟哈希函数是可以更改的
function memoized(fn) {
var lookupTable = {};
var keymaker = function (args) {
console.log(JSON.stringify(args));
return JSON.stringify(args)
};
return function () {
var key = keymaker.call(this, arguments);
return lookupTable[key] || (
lookupTable[key] = fn.apply(this, arguments))
}
}
function simpleDist(pointA, pointB) {
var x = pointA.x - pointB.x,
y = pointA.y - pointB.y;
return Math.sqrt(x * x + y * y);
}
function distanceFrom(pointC) {
return function (pointA, pointB) {
var distA = simpleDist(pointA, pointC);
var distB = simpleDist(pointB, pointC);
if (distA < distB) return -1;
if (distA > distB) return 1;
return 0;
}
}
var distanceFromC = memoized(distanceFrom({x:0, y:0}));
[{x:10, y:10}, {x:1, y:2},{x:3, y:1}, {x:3, y:2}].sort(distanceFromC);
旧的
在这里,我使用了闭包的事实,以及即使在外部函数返回之后,它们也可以访问外部函数参数的事实。
例如,您可以在David Herman的高效Javascript第2.11章或更新中了解更多信息
下面是如何修改我的代码以使用memoize decorator。
它的好处是,记忆化不太依赖于比较对象的实现。
我不确定JSON.stringify的速度有多快,但看起来已经足够快了,毕竟哈希函数是可以更改的
function memoized(fn) {
var lookupTable = {};
var keymaker = function (args) {
console.log(JSON.stringify(args));
return JSON.stringify(args)
};
return function () {
var key = keymaker.call(this, arguments);
return lookupTable[key] || (
lookupTable[key] = fn.apply(this, arguments))
}
}
function simpleDist(pointA, pointB) {
var x = pointA.x - pointB.x,
y = pointA.y - pointB.y;
return Math.sqrt(x * x + y * y);
}
function distanceFrom(pointC) {
return function (pointA, pointB) {
var distA = simpleDist(pointA, pointC);
var distB = simpleDist(pointB, pointC);
if (distA < distB) return -1;
if (distA > distB) return 1;
return 0;
}
}
var distanceFromC = memoized(distanceFrom({x:0, y:0}));
[{x:10, y:10}, {x:1, y:2},{x:3, y:1}, {x:3, y:2}].sort(distanceFromC);
旧的
在这里,我使用了闭包的事实,以及即使在外部函数返回之后,它们也可以访问外部函数参数的事实。
您可以在David Herman的高效Javascript第2.11章或中阅读更多关于它的内容,我认为您的思路非常正确 如果您试图优化代码行,那么可以使用来减少锅炉板阵列代码中的一些代码 使用 我认为简化实现的唯一直接方法是使用优化对SimpleList的调用
function simpleDist(pointA, pointB) {
var x = pointA.x - pointB.x,
y = pointA.y - pointB.y;
return Math.sqrt(x*x + y*y);
}
// fn(point) memoizer
var memoizer = (function(fn) {
var cache = {};
return function(pointB) {
var key = pointB.x + "|" + pointB.y; // simple key hashing
return cache[key] || (cache[key] = fn(pointB));
};
}());
function sortByDist (pointRef, pointArray) {
// partially apply pointRef to simpleDist and memoize
var distanceFrom = memoizer(function(pointB) { return simpleDist(pointRef, pointB); });
// sort
return pointArray.sort(function(a,b) {
return distanceFrom(a) - distanceFrom(b);
});
}
由于simpleDist是一个纯函数——相同的输入总是产生相同的输出——这里的记忆器可以避免重复距离计算的成本。只需稍微增加一点设置开销,排序就变成了一个简单的比较器。我认为您的思路基本正确 如果您试图优化代码行,那么可以使用来减少锅炉板阵列代码中的一些代码 使用 我认为简化实现的唯一直接方法是使用优化对SimpleList的调用
function simpleDist(pointA, pointB) {
var x = pointA.x - pointB.x,
y = pointA.y - pointB.y;
return Math.sqrt(x*x + y*y);
}
// fn(point) memoizer
var memoizer = (function(fn) {
var cache = {};
return function(pointB) {
var key = pointB.x + "|" + pointB.y; // simple key hashing
return cache[key] || (cache[key] = fn(pointB));
};
}());
function sortByDist (pointRef, pointArray) {
// partially apply pointRef to simpleDist and memoize
var distanceFrom = memoizer(function(pointB) { return simpleDist(pointRef, pointB); });
// sort
return pointArray.sort(function(a,b) {
return distanceFrom(a) - distanceFrom(b);
});
}
由于simpleDist是一个纯函数——相同的输入总是产生相同的输出——这里的记忆器可以避免重复距离计算的成本。只需稍微增加一点设置开销,排序就会变成一个简单的比较器。只需一个提示,就可以为排序中的每个迭代执行距离计算。对于最坏情况下的性能,它可能类似于对SimpleList的2n^2或2n log n调用。与op实现相反,op实现对SimpleList进行n次调用。@32bitkid,是的,您完全正确,应该注意这一点@这是一个极好的音符。就表面价值美学而言,我更喜欢这个答案,但性能至关重要。不过,我必须感谢你拓宽了我对闭包的认识。是的,我很高兴@32bitkid指出了这一点,因为我太受美学的驱使了。好吧,也许至少在其他方面会有所帮助day@DanieClawson如果您认为性能是超关键的,因为sqrt是一个函数,您并不真正关心实际距离-只是它的相对顺序-您可以放弃sqrt调用,获得相同的顺序,并为自己节省一些数学。只是提醒一下,这将对排序中的每个迭代执行距离计算。对于最坏情况下的性能,它可能类似于对SimpleList的2n^2或2n log n调用。与op实现相反,op实现对SimpleList进行n次调用。@32bitkid,是的,您完全正确,应该注意这一点@这是一个极好的音符。就表面价值美学而言,我更喜欢这个答案,但性能至关重要。不过,我必须感谢你拓宽了我对闭包的认识。是的,我很高兴@32bitkid指出了这一点,因为我太受美学的驱使了。好吧,也许至少在其他方面会有所帮助day@DanieClawson如果您认为性能是非常关键的,因为sqrt是一个函数,您并不真正关心实际距离-只是它的相对顺序-您可以放弃sqrt调用,获得相同的顺序,并节省一些数学计算。