Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Javascript中,如何根据点到参考点的距离对点数组进行排序?_Javascript_Arrays_Sorting - Fatal编程技术网

在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调用,获得相同的顺序,并节省一些数学计算。