根据数组中坐标的频率创建多个数组

时间:2011-10-03 00:41:07

标签: javascript arrays coordinates frequency

使用JavaScript,我想基于重合的点将一个大的坐标数组拆分成更小的数组。我不是100%确定如何在代码中编写以下内容,但它描述了我正在尝试实现的目标:

  1. 遍历数组

    var A = [(1,2)(1,3)(2,3)(9,10)(9,11)(10,11)];

  2. 合并包含任何匹配/相同坐标点的对:

    var B = (1,2)(1,3)(2,3)

    var C = (9,10)(9,11)(10,11)

  3. 合并匹配/相同点,并从第2点的组合中创建新的较小数组

    var D = [1,2,3]

    var E = [9,10,11]

  4. 我可以得到帮助吗?

2 个答案:

答案 0 :(得分:1)

工作回答:http://jsfiddle.net/y3h9L/

好的,所以如果我理解要求A是一维数组,假设在x,y对中有偶数个元素。

A = [1,2,  1,3,  2,3,  9,10,  9,11,  10,11]
// output should be
[ [1,2,3], [9,10,11] ]

// but if you add an extra pair that links the two halves, say add 2,11
A2 = [1,2,  1,3,  2,3,  9,10,  9,11,  10,11,   2,11]
// then all are related so output should be
[ [1,2,3,9,10,11] ]

我没有努力改进或优化以下代码,但它确实有效:

// single dimensional array of x,y pairs
var A = [1,2,  1,3,  2,3,  9,10,  9,11,  10,11];

// create a working copy of A so that we can remove elements
// and still keep the original A intact.
var workingCopy = A.slice(0, A.length),
    matchedPairs = [],
    currentMatches,
    finalCombinations = [],
    x, y, i, j,
    tempArray;

while (workingCopy.length > 0) {
   currentMatches = [];
   currentMatches.push([workingCopy.shift(),workingCopy.shift()]);

   workingCopyLoop:
   for (x=0,y=1; x < workingCopy.length;) {
      for (i=0; i < currentMatches.length; i++){
         if (workingCopy[x] === currentMatches[i][0]
            || workingCopy[y] === currentMatches[i][1]) {
            currentMatches.push([workingCopy.shift(),workingCopy.shift()]);
            // go back to the beginning of workingCopyLoop
            x=0;
            y=1;
            continue workingCopyLoop;
         }
      }

      x += 2;
      y += 2;
   }   

   matchedPairs.push(currentMatches);
}

for (i=0; i<matchedPairs.length; i++){
   tempArray = [];
   for (j=0; j<matchedPairs[i].length; j++) {
      // I assume you have a new enough version of JS that you have Array.indexOf()
      if (-1 === tempArray.indexOf(matchedPairs[i][j][0]))
         tempArray.push(matchedPairs[i][j][0]);
      if (-1 === tempArray.indexOf(matchedPairs[i][j][1]))
         tempArray.push(matchedPairs[i][j][1]);
   }
   finalCombinations.push(tempArray);
}

for (i=0; i<finalCombinations.length; i++)
   console.log(finalCombinations[i]);

// console.log shows that finalCombinations = [ [1,2,3], [9,10,11] ]

如果效果不明显,请使用调试器和/或铅笔和纸张进行操作。

答案 1 :(得分:1)

我必须说你的问题还不清楚,但我想我明白了。

换句话说,你所说的是: 我有一个包含一堆数字的数组,逻辑上它们代表坐标,并不是坐标是主数组中的子数组,只是看它们2乘2,但它是一个线性数组。

您想要的是检测相邻坐标并生成包含它们的新数组。

之后,您希望通过新数组并生成包含unique-elements的新数组。

那就是问题,现在是答案。首先,第二点取决于你想走多远,我认为它是x,y坐标的正常网格,但你想要去的距离是多少?以下仅适用于中间相邻,最多8个点可以与单个点相邻。

[1,1][2,1][3,1]
[1,2][2,2][3,2]
[1,3][2,3][3,3]

可能是网格的表示,如果你的主数组有[2,2]坐标,你想要构建一个以你找到的所有邻接开始的数组,就像主数组那样[3] ,2],然后你想把它添加到[2,2]的子阵列。

我真的不是在编写代码我只是要解释你可以使用的各种算法。 要构建第二个点数组,我们可以将它们称为Adjacents Arrays(AA):

第一个坐标将始终构建第一个AA 要查找邻接,您将循环通过主阵列并对每个坐标执行“邻接检查”:第二个x ==(第一个x-1,x或x + 1)和第二个y ==(第一个y-1 ,y或y + 1),如果它通过那么pop / push,如果不通过... next。 如果您通过主阵列完成循环,则表示AA已完成,您必须使用下一个坐标启动新的AA。 重复,直到主数组为空。

然后创建unique-element-array是一个非常简单的循环,我编写了一个类似的函数来执行类似的操作,但是它创建了一个包含该元素的数组以及它在数组中出现的次数(实例): / p>

function uniqueCnt( ori) { // agroups and counts unique elements of an array, scrubs '' elements
 var res = []; // resulting array, ori parameter stands for original array
 for( let cntA = 0; cntA < ori.length; cntA++) { 
      for( cntB = 0; cntB < res.length; cntB += 2) if( ori[cntA] == res[cntB]) { res[cntB + 1]++; break; } // if it matches means it's another instance then increase that element count
     if( cntB == res.length && ori[cntA] != '') res.push( ori[cntA], 1); // New element found then push it and start count
 }
 return res; // returns the agrouped array 0:element 1:instances...
}

如果你不想要一个实例计数,那么你需要一个更简单的函数,你可以尝试修改这个。