如何根据特定条件拆分数组?

时间:2016-09-04 08:11:25

标签: javascript arrays grouping

我有一个数组,其中包含一些相邻矩形的组:

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/

修改 感谢Tobias K的最终解决方案:https://jsfiddle.net/j1of5p4c/4/

3 个答案:

答案 0 :(得分:1)

没有转换你的反应,这是我的解决方案:



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){
	  return rectangles[i];
	}
  }
  return undefined;
}

function isNeighbour(p1, p2) {
  var r1 = getRectangle(p1);
  var r2 = getRectangle(p2);
  if (r1 == undefined || r2 == undefined){
  	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){
	  results.push(paths[i]);
	  continue;
	}
  	for (var j=0; j<paths[i].length; j++){
	  if (j+1 == paths[i].length){
	  	neighb.push(paths[i][j]);
	  	results.push(neighb);
	  	neighb = [];
		continue;
	  }
	  while(isNeighbour(paths[i][j], paths[i][j+1])){
	  	neighb.push(paths[i][j]);
		j = j+1;
	  }
	  neighb.push(paths[i][j]);
	  results.push(neighb);
	  neighb = [];
  	}
  }
  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]);
  }
}
&#13;
&#13;
&#13;

答案 1 :(得分: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 } }

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

&#13;
&#13;
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);
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以使用MapArray#forEach作为内部循环的pathsArray#reduce的外部循环,并使最后一个节点可用于内部的比较部分用于分配给新数组或仅附加到最后一个结果数组的回调函数。

&#13;
&#13;
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);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;