【问题标题】:Loop logic for drawing line javascript绘制线条javascript的循环逻辑
【发布时间】:2016-06-09 20:26:22
【问题描述】:

我有以下两个数组:

var element_1 = new Array([x1,y1],[x2,y2],[x3,y3],[x4,y4]);
var element_2 = new Array([x1,y1],[x2,y2],[x3,y3],[x4,y4]);

逻辑: 我想运行一个循环(嵌套),其中element_1 的每个元素(例如[x1,y1])与element_2 的每个元素进行比较,并且它们之间的 最短距离 应在循环(我知道如何计算最短路径)。这里棘手的部分是我需要一个参考,哪一对过去最短,然后获得[x1,y1][x2,y2] 组合来画一条线。

样本数据:

var element_1 = new Array([10,0],[20,10],[10,20],[0,10]);
var element_2 = new Array([10,30],[20,40],[10,50],[0,40]);

应在 [10,20] 和 [10,30] 之间划线。另外,我会以某种方式需要将坐标存储在某处以将其传递给画线函数

我该怎么做?任何线索将不胜感激。

【问题讨论】:

  • 您能否提供一组实际坐标,以及您期望的结果?
  • @blex 坐标在单击元素时动态存储在数组中。 4 [x,y] 对是矩形锚点的坐标(高度和宽度的中点)。因此 2 个数组有锚点或 2 个元素。因此,目标是找到最短的连接锚点及其 x,y 值以在它们之间画一条线
  • @Redu 这是一个打字错误。纠正它。谢谢!
  • 矩形?为什么不直接存储el=[x,y,w,h] ...
  • @RokoC.Buljan 那是因为我需要传入的行仅加入矩形上的某个点。想象一下 UML 图

标签: javascript arrays loops


【解决方案1】:

我会这样做:

var element_1 = [[0,0],[1,2],[5,3],[6,8]];
var element_2 = [[0,1],[1,4],[5,9],[9,8]];

var closest = {a: false, b: false, distance: false};

for(var i=0; i<element_1.length; i++) {
  for(var j=0; j<element_2.length; j++) {
    var distance = calculate_distance(element_1[i], element_2[j]);
    console.log('Distance between element_1['+i+'] and element_2['+j+']: ' + distance);
    if(closest.distance === false || distance < closest.distance) {
      closest = {a: element_1[i], b: element_2[j], distance: distance};
    }
  }
}

console.log('The shortest path is between '+closest.a+' and '+closest.b+', which is '+closest.distance);

function calculate_distance(a, b) {
  var width  = Math.abs( a[0] - b[0] ),
      height = Math.abs( a[1] - b[1] ),
      hypothenuse = Math.sqrt( width*width + height*height );
  return hypothenuse;
}

正如Roko C. Buljan 所说,在您的情况下,您可以将new Array() 替换为[]Here's why.

【讨论】:

  • 您错过了使用Math.hypot 的好机会;)
  • 哇...为什么 JavaScript 总是对我保密?也许我应该阅读文档;)谢谢,我会使用它!
  • 不!不要使用它,等待一年......或三年。这是一个 ES5 特性。 :D(即……还记得吗?)
  • 哦,我明白了......好吧,很高兴知道有一天它会得到全面支持。
  • @Arihant 是的,你可以通过closest.a[0] 得到 x,closest.a[1] 得到 y。 closest.b 也是如此。
【解决方案2】:

我非常喜欢这个问题。它启发我发明了一个通用的 Array 方法来对两个数组的其他项应用回调。所以我称它为Array.prototype.withEachOther()。它所做的正是@blex 在他的嵌套 for 循环解决方案中所做的。它将操作(由回调提供)应用于每个数组项以及另一个数组的项。让我们看看它是如何工作的。

Array.prototype.withEachOther = function(a,cb,s=0){
  return this.reduce((p,et) => a.reduce((q,ea) => cb(et,ea,q),p),s);
};
var element_1 = [[10,0],[20,10],[10,20],[0,10]],
    element_2 = [[10,30],[20,40],[10,50],[0,40]],
           cb = (p1,p2,q) => {var h = Math.hypot(p1[0]-p2[0],p1[1]-p2[1]);
                              return h < q.d ? {d:h,p1:p1,p2:p2} : q},
      minDist = element_1.withEachOther(element_2,cb,{d:Number.MAX_SAFE_INTEGER,p1:[],p2:[]});
console.log(minDist);

所以让我们解释一下发生了什么。

Array.prototype.withEachOther = function(a,cb,s=0){
  return this.reduce((p,et) => a.reduce((q,ea) => cb(et,ea,q),p),s);
};

是一个可重用的函数。它将执行回调函数中提供的操作,并使用两个数组的其他元素。它需要 3 个参数 (a,cb,s=0)

  • a 是第二个数组,我们将对调用 .withEachOther 的数组中的每个项目应用回调。
  • cb 是回调。下面我将解释针对这个问题应用的回调。
  • s=0 是我们将开始使用的初始值(默认值为 0)。它可以是任何东西,具体取决于回调函数。

return this.reduce((p,et) =&gt; a.reduce((q,ea) =&gt; cb(et,ea,q),p),s);

这部分是函数的核心。如您所见,它有两个嵌套的 reduce。外部reduce 有一个由s 指定的初始值,如上所述提供。初始值最初分配给外部 reduce 回调的 p 参数,另一个参数 et 与调用数组的每个项目一一分配。 (et他的)。在外部归约中,我们调用另一个归约(内部归约)。内部reduce从前一个循环结果的初始值开始,即外部reduce的p,每次计算后将结果返回给它的缩减值变量qq 是我们的内存,并在回调中进行测试,看看我们是保持原样还是用我们的计算结果替换它。在内部 reduce 完成一个完整的回合后,它会将 q 返回到 p,并且相同的机制将再次运行,直到我们完成调用 .withEachOther 的数组的所有项目。

cb = (p1,p2,q) => {var h = Math.hypot(p1[0]-p2[0],p1[1]-p2[1]);
                   return h < q.d ? {d:h,p1:p1,p2:p2} : q}

回调对于这个问题是特殊的。它将接收两个点(每个点都有 x 和 y 坐标) 将计算它们之间的距离并将其与先前进行的计算进行比较。如果它更小,它将通过返回这个新值来替换q;如果不是,它将按原样返回q

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 2017-01-26
    • 2022-10-15
    • 2018-11-02
    相关资源
    最近更新 更多