2016-09-04 73 views
2

我有一个包含一些相邻矩形的基团的数组:如何基于特定条件拆分数组的数组?

var paths = [ 
    [3,4,6,7], 
    [8,10], 
    [13] 
]; 

的矩形被定义如下:

var rectangles = [ 
    {id:1,left:[],right:[2]}, 
    {id:2,left:[1],right:[11]}, 
    {id:3,left:[2],right:[4]}, 
    {id:4,left:[3],right:[5]}, 
    {id:5,left:[11],right:[6,12]}, 
    {id:6,left:[5],right:[7]}, 
    {id:7,left:[6],right:[]}, 
    {id:8,left:[],right:[9]}, 
    {id:9,left:[8],right:[10]}, 
    {id:10,left:[9],right:[2]}, 
    {id:11,left:[2],right:[5]}, 
    {id:12,left:[5],right:[]}, 
    {id:13,left:[],right:[9]} 
]; 

从矩形定义,我看到的矩形4和6是不邻居,因为4不是6的右边,而6不是4的左边。对于8和10来说是一样的。

现在,我想将路径数组拆分为每个相邻矩形组都有单独的条目,像这样:

result = [ 
    [3,4], 
    [6,7], 
    [8], 
    [10], 
    [13] 
]; 

当我找到两个非相邻矩形的两个连续id时,如何分割数组并创建新条目?

拨弄测试数据:https://jsfiddle.net/4jpy84k4/

编辑: 最终解决方案感谢托比亚斯ķ:https://jsfiddle.net/j1of5p4c/4/

回答

1

无需转换您的reactangles这是我的解决方案:

var paths = [ 
 
    [3,4,6,7], 
 
    [8,10], 
 
    [13] 
 
]; 
 

 
var rectangles = [ 
 
{id:1,left:[],right:[2]}, 
 
{id:2,left:[1],right:[11]}, 
 
{id:3,left:[2],right:[4]}, 
 
{id:4,left:[3],right:[5]}, 
 
{id:5,left:[11],right:[6,12]}, 
 
{id:6,left:[5],right:[7]}, 
 
{id:7,left:[6],right:[]}, 
 
{id:8,left:[],right:[9]}, 
 
{id:9,left:[8],right:[10]}, 
 
{id:10,left:[9],right:[2]}, 
 
{id:11,left:[2],right:[5]}, 
 
{id:12,left:[5],right:[]}, 
 
{id:13,left:[],right:[9]} 
 
]; 
 

 
function getRectangle(index){ 
 
    for (var i=0; i<rectangles.length; i++){ 
 
    if (rectangles[i].id == index){ 
 
\t return rectangles[i]; 
 
\t } 
 
    } 
 
    return undefined; 
 
} 
 

 
function isNeighbour(p1, p2) { 
 
    var r1 = getRectangle(p1); 
 
    var r2 = getRectangle(p2); 
 
    if (r1 == undefined || r2 == undefined){ 
 
    \t return false; 
 
    } 
 
    return r1.left.indexOf(p2) >= 0 || r1.right.indexOf(p2) >= 0 || r2.left.indexOf(p1) >= 0 || r2.right.indexOf(p1) >= 0; 
 
} 
 

 
function groupPaths(paths) { 
 
    var results = []; 
 
    var neighb = []; 
 
    for (var i=0; i<paths.length; i++){ 
 
    if (paths[i].length == 1){ 
 
\t results.push(paths[i]); 
 
\t continue; 
 
\t } 
 
    \t for (var j=0; j<paths[i].length; j++){ 
 
\t if (j+1 == paths[i].length){ 
 
\t \t neighb.push(paths[i][j]); 
 
\t \t results.push(neighb); 
 
\t \t neighb = []; 
 
\t \t continue; 
 
\t } 
 
\t while(isNeighbour(paths[i][j], paths[i][j+1])){ 
 
\t \t neighb.push(paths[i][j]); 
 
\t \t j = j+1; 
 
\t } 
 
\t neighb.push(paths[i][j]); 
 
\t results.push(neighb); 
 
\t neighb = []; 
 
    \t } 
 
    } 
 
    return results; 
 
} 
 

 
var res = groupPaths(paths); 
 
for (var i=0; i<res.length; i++){ 
 
    for(var j=0; j<res[i].length; j++){ 
 
    console.log(i + ': ' + res[i][j]); 
 
    } 
 
}

+0

我刚刚更新了您的解决方案的示例小提琴,您可以看到邻居的确切定义。除此之外,只有一个疑问:为什么结果是:[[3,4],[6,7],[8],[10],[[13]]]?最后一项应该简单[13]。 – deblocker

+0

我看不到,为什么13应该包裹两次,因此如果问:“if(j + 1 == paths [i] .length){” –

+0

It's here:'results。push([paths [i]]);'应该是'results.push(paths [i]);'请更新您的答案,以便我可以接受它:-) – deblocker

0

这是你可以怎么做。但首先,为了提高效率,我必须将您的rectangles参考数据转换为更实用的形式。 rectangleIds查找对象看起来像这样;

{ '1': { left: 0, right: 2 }, 
    '2': { left: 1, right: 11 }, 
    '3': { left: 2, right: 4 }, 
    '4': { left: 3, right: 5 }, 
    '5': { left: 11, right: 6 }, 
    '6': { left: 5, right: 7 }, 
    '7': { left: 6, right: 0 }, 
    '8': { left: 0, right: 9 }, 
    '9': { left: 8, right: 10 }, 
    '10': { left: 9, right: 2 }, 
    '11': { left: 2, right: 5 }, 
    '12': { left: 5, right: 0 }, 
    '13': { left: 0, right: 9 } } 

然后它只是两个嵌套减少的问题。

var paths = [ 
 
       [3,4,6,7], 
 
       [8,10], 
 
       [13] 
 
       ], 
 

 
    rectangles = [ 
 
       {id:1,left:[],right:[2]}, 
 
       {id:2,left:[1],right:[11]}, 
 
       {id:3,left:[2],right:[4]}, 
 
       {id:4,left:[3],right:[5]}, 
 
       {id:5,left:[11],right:[6,12]}, 
 
       {id:6,left:[5],right:[7]}, 
 
       {id:7,left:[6],right:[]}, 
 
       {id:8,left:[],right:[9]}, 
 
       {id:9,left:[8],right:[10]}, 
 
       {id:10,left:[9],right:[2]}, 
 
       {id:11,left:[2],right:[5]}, 
 
       {id:12,left:[5],right:[]}, 
 
       {id:13,left:[],right:[9]} 
 
       ], 
 
rectangleIds = rectangles.reduce((o,r) => (o[r.id] = {left: r.left[0] || 0, right: r.right[0] || 0},o),{}), 
 
orderedPaths = paths.reduce((sol,p) => sol.concat(p.reduce((res,c,i,a) => rectangleIds[c].left === a[i-1] || 
 
                      rectangleIds[c].right === a[i-1] ? (res[res.length-1].push(c),res) 
 
                              : res.concat([[c]]) 
 
                      ,[])) 
 
             ,[]); 
 
console.log(orderedPaths);

+0

我感谢您的帮助,真的,你能解释一下你怎么来第5项:只有一个矩形,右侧第6项?可以从提供的样本数据中扣除? THX – deblocker

+0

@deblocker Wow..what's that .. :)它来自您的示例数据。但由于我只考虑了第一项,它的工作。项目5有没有可能在右边有两个相邻的矩形..? – Redu

0

你可以使用的pathsArray#reduce为内环外环和具有回调的内部的最后一个节点avaliable到比较一部分分配给一个MapArray#forEach一个新的数组或只追加到最后的结果数组。

var paths = [[3, 4, 6, 7], [8, 10], [13]], 
 
    rectangles = [{ id: 1, left: [], right: [2] }, { id: 2, left: [1], right: [11] }, { id: 3, left: [2], right: [4] }, { id: 4, left: [3], right: [5] }, { id: 5, left: [11], right: [6, 12] }, { id: 6, left: [5], right: [7] }, { id: 7, left: [6], right: [] }, { id: 8, left: [], right: [9] }, { id: 9, left: [8], right: [10] }, { id: 10, left: [9], right: [2] }, { id: 11, left: [2], right: [5] }, { id: 12, left: [5], right: [] }, { id: 13, left: [], right: [9] }], 
 
    rectanglesMap = new Map, 
 
    result = []; 
 

 
rectangles.forEach(function (a) { 
 
    rectanglesMap.set(a.id, a); 
 
}); 
 
paths.forEach(function (a) { 
 
    a.reduce(function (r, b, i) { 
 
     if (!i || r !== rectanglesMap.get(b).left[0]) { 
 
      result.push([b]); 
 
     } else { 
 
      result[result.length - 1].push(b); 
 
     } 
 
     return b; 
 
    }, undefined); 
 
}); 
 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

对不起,我不能假设left [0]就足够让邻居了。 – deblocker