Javascript 如何有效地将列表项与所有其他列表项一起检查?

Javascript 如何有效地将列表项与所有其他列表项一起检查?,javascript,optimization,Javascript,Optimization,有没有办法优化这种搜索方法 for (var i=0;i<dots.length;i++) { var blist = []; for (var n=0;n<dots.length;n++) { if (dots[n][1]>(dots[i][1]-90) && dots[n][1]<(dots[i][1]+90) && dots[n

有没有办法优化这种搜索方法

for (var i=0;i<dots.length;i++) {
        var blist = [];
        for (var n=0;n<dots.length;n++) {
            if (dots[n][1]>(dots[i][1]-90) 
            && dots[n][1]<(dots[i][1]+90) 
            && dots[n][2]>(dots[i][2]-90) 
            && dots[n][2]<(dots[i][2]+90)) {
                if (!(n === i)) blist.push(n);
            }
        }

每秒运行一百万次,那么有没有办法对此进行优化?

或许可以尝试使用这样的点数据结构

var Dot = function(){
 var x = 0;
 var y = 0;
 var Up;
 var Right;
 var Left;
 var Down;

 function init(xVal,yVal)
 {
  x = xVal;
  y = yVal;
 }

 function GetUp()
 {
  return Up;
 }

 function SetUp(UpDot)
 {
  Up = UpDot;
 }

 return 
 {
  init: init,
  GetUp: GetUp,
  SetUp: SetUp
 };
};
var Dots = [];
var firstDot = new Dot();
Dots.push(firstDot);
var secondDot = new Dot();
secondDot.init(0,90);
secondDot.SetUp(firstDot);
Dots.push(secondDot);
然后像这样使用它

var Dot = function(){
 var x = 0;
 var y = 0;
 var Up;
 var Right;
 var Left;
 var Down;

 function init(xVal,yVal)
 {
  x = xVal;
  y = yVal;
 }

 function GetUp()
 {
  return Up;
 }

 function SetUp(UpDot)
 {
  Up = UpDot;
 }

 return 
 {
  init: init,
  GetUp: GetUp,
  SetUp: SetUp
 };
};
var Dots = [];
var firstDot = new Dot();
Dots.push(firstDot);
var secondDot = new Dot();
secondDot.init(0,90);
secondDot.SetUp(firstDot);
Dots.push(secondDot);

显然,需要添加和配置更多内容,以符合您的情况。然而,这将允许你做的是迭代点,然后检查是否存在一个近点,使时间为O(n)而不是O(n^2),从而为你节省900000次检查。

也许可以尝试使用这样的点的数据结构

var Dot = function(){
 var x = 0;
 var y = 0;
 var Up;
 var Right;
 var Left;
 var Down;

 function init(xVal,yVal)
 {
  x = xVal;
  y = yVal;
 }

 function GetUp()
 {
  return Up;
 }

 function SetUp(UpDot)
 {
  Up = UpDot;
 }

 return 
 {
  init: init,
  GetUp: GetUp,
  SetUp: SetUp
 };
};
var Dots = [];
var firstDot = new Dot();
Dots.push(firstDot);
var secondDot = new Dot();
secondDot.init(0,90);
secondDot.SetUp(firstDot);
Dots.push(secondDot);
然后像这样使用它

var Dot = function(){
 var x = 0;
 var y = 0;
 var Up;
 var Right;
 var Left;
 var Down;

 function init(xVal,yVal)
 {
  x = xVal;
  y = yVal;
 }

 function GetUp()
 {
  return Up;
 }

 function SetUp(UpDot)
 {
  Up = UpDot;
 }

 return 
 {
  init: init,
  GetUp: GetUp,
  SetUp: SetUp
 };
};
var Dots = [];
var firstDot = new Dot();
Dots.push(firstDot);
var secondDot = new Dot();
secondDot.init(0,90);
secondDot.SetUp(firstDot);
Dots.push(secondDot);

显然,需要添加和配置更多内容,以符合您的情况。然而,这将允许你做的是迭代点,然后检查是否存在一个近点,使时间为O(n)而不是O(n^2),从而节省900000次检查。

将时间减半的一种方法是不重复检查每一对:

for (var i = 0, len = dots.length; i < len - 1; i++) {
    var blist = [];
    for (var n = i + 1; n < len; n++) {
        if (dots[n][1]>(dots[i][1]-90) 
        && dots[n][1]<(dots[i][1]+90) 
        && dots[n][2]>(dots[i][2]-90) 
        && dots[n][2]<(dots[i][2]+90)) {
            blist.push(i);
            blist.push(n);
        }
    }
}
for(变量i=0,len=dots.length;i(点[i][1]-90)
&&点[n][1](点[i][2]-90)

&&点[n][2]将时间减半的一种方法是不要对每一对进行双重检查:

for (var i = 0, len = dots.length; i < len - 1; i++) {
    var blist = [];
    for (var n = i + 1; n < len; n++) {
        if (dots[n][1]>(dots[i][1]-90) 
        && dots[n][1]<(dots[i][1]+90) 
        && dots[n][2]>(dots[i][2]-90) 
        && dots[n][2]<(dots[i][2]+90)) {
            blist.push(i);
            blist.push(n);
        }
    }
}
for(变量i=0,len=dots.length;i(点[i][1]-90)
&&点[n][1](点[i][2]-90)

&&dots[n][2]这是一个解决方案的草图。这可能与TravisJ提出的想法相同,尽管我不清楚。这实际上只是一个草图,需要大量代码才能实现

如果将空间划分为90个单位x 90个单位的部分,则特定部分中的点只能与该部分中的点或该部分八个相邻部分之一中的点足够接近。这可以显著减少需要比较的对数。当然,成本是算法复杂性:

  • 首先创建一个数据结构来表示网格部分。它们可能仅由左上角表示,因为它们的高度和宽度将固定在90,除了可能在后缘,这可能无关紧要。假设一个矩形曲面,每个曲面可能有三个、五个或八个相邻曲面(分别为角部、边缘和内部部分)
  • 通过点循环,确定它们所在的区域。如果总网格从0开始,则使用一些
    Math.floor(something/90)
    操作,这应该相对简单
  • 对于每个部分,在其自身和每个相邻部分上运行上面的循环,以找到匹配集。您可以使用我前面答案中循环的缩短版本
  • 为了进一步优化,您还可以减少要检查的邻居的数量。如果Section3,7与Section3,8进行比较,则Section3,8没有理由也与Section3,7进行比较。因此,您只检查邻居的某个子集,例如其节号的x和y分量大于或者等于他们自己的
我没有测试过这个,除了在我的头脑中。它应该可以工作,但我没有尝试编写任何代码。代码也不会很琐碎。我不认为这需要几周的工作,但也不是几分钟内就能完成的


我相信它可以显著提高速度,但这取决于有多少匹配,相对于节数有多少点。

这里是一个解决方案的草图。这可能与TravisJ所建议的想法相同,尽管我不清楚。它实际上只是一个草图,需要大量代码实施

如果将空间划分为90个单位x 90个单位的部分,则特定部分中的点只能与该部分中的点或该部分八个相邻部分之一中的点足够接近。这可以显著减少需要比较的对数。当然,成本是算法复杂性:

  • 首先创建一个数据结构来表示网格部分。它们可能仅由左上角表示,因为它们的高度和宽度将固定在90,除了可能在后缘,这可能无关紧要。假设一个矩形曲面,每个曲面可能有三个、五个或八个相邻曲面(分别为角部、边缘和内部部分)
  • 通过点循环,确定它们所在的区域。如果总网格从0开始,则使用一些
    Math.floor(something/90)
    操作,这应该相对简单
  • 对于每个部分,在其自身和每个相邻部分上运行上面的循环,以找到匹配集。您可以使用我前面答案中循环的缩短版本
  • 为了进一步优化,您还可以减少要检查的邻居的数量。如果Section3,7与Section3,8进行比较,则Section3,8没有理由也与Section3,7进行比较。因此,您只检查邻居的某个子集,例如其节号的x和y分量大于或者等于他们自己的
我没有测试过这个,除了在我的头脑中。它应该可以工作,但我没有尝试编写任何代码。代码也不会很琐碎。我不认为这需要几周的工作,但也不是几分钟内就能完成的


我相信它可以显著提高速度,但这将取决于有多少匹配,相对于节数有多少点。

将点放入数据结构。
var n=I+1
内部循环初始化?(如果您需要双向匹配,可能需要一些额外的逻辑-您如何处理
blist
?)@nnnnnn从b中选取这一点后