![](/img/trans.png)
[英]Build a tree array (3 dimensional) from a flat array in Typescript/Javascript
[英]JavaScript Flat one dimensional array to tree
我将以下对象堆叠在一维数组中:
var colors = ["#FF0000", "#00FF00", "#0000FF", "#FF00FF", "#00FFFF"];
var array1D = [
{ level: 1, x: 0, y: 0 },
{ level: 1, x: 0, y: 1 },
{ level: 1, x: 1, y: 0 },
{ level: 4, x: 8, y: 8 },
{ level: 4, x: 8, y: 9 },
{ level: 5, x: 18, y: 16 },
{ level: 5, x: 18, y: 17 },
{ level: 5, x: 19, y: 16 },
{ level: 5, x: 19, y: 17 },
{ level: 5, x: 18, y: 18 },
{ level: 5, x: 18, y: 19 },
{ level: 5, x: 19, y: 18 },
{ level: 5, x: 19, y: 19 },
{ level: 4, x: 8, y: 10 },
{ level: 4, x: 8, y: 11 },
{ level: 5, x: 18, y: 20 },
{ level: 5, x: 18, y: 21 },
{ level: 5, x: 19, y: 20 },
{ level: 5, x: 19, y: 21 },
{ level: 4, x: 9, y: 11 },
{ level: 5, x: 20, y: 16 },
{ level: 5, x: 20, y: 17 },
{ level: 5, x: 21, y: 16 },
{ level: 5, x: 21, y: 17 },
{ level: 5, x: 20, y: 18 },
{ level: 5, x: 20, y: 19 },
{ level: 5, x: 21, y: 18 },
{ level: 5, x: 21, y: 19 },
{ level: 4, x: 11, y: 8 },
{ level: 5, x: 22, y: 18 },
{ level: 5, x: 22, y: 19 },
{ level: 5, x: 23, y: 18 },
{ level: 5, x: 23, y: 19 },
{ level: 5, x: 20, y: 20 },
{ level: 5, x: 20, y: 21 },
{ level: 5, x: 21, y: 20 },
{ level: 5, x: 21, y: 21 },
{ level: 4, x: 10, y: 11 },
{ level: 5, x: 22, y: 20 },
{ level: 5, x: 22, y: 21 },
{ level: 5, x: 23, y: 20 },
{ level: 5, x: 23, y: 21 },
{ level: 4, x: 11, y: 11 },
{ level: 2, x: 2, y: 3 },
{ level: 2, x: 3, y: 2 },
{ level: 2, x: 3, y: 3 }
];
它基本上是一个四叉树结构,因此您无需验证是否可以从中构建树。
在视觉上它看起来像下图:
viz 的代码非常简单:
quad.sort(function(a_, b_){ return a_.level - b_.level; })
var canvas = document.createElement("canvas");
document.body.appendChild(canvas)
canvas.width = 512;
canvas.height = 512;
var ctx = canvas.getContext("2d");
quad.forEach(function(node_){
ctx.fillStyle = colors[node_.level - 1];
var w = 256;
for(var i = 0; i < node_.level; i++) { w /= 2; }
var x = 256;
for(var i = 0; i < node_.level; i++) { x /= 2; }
x *= node_.x;
var y = 256;
for(var i = 0; i < node_.level; i++) { y /= 2; }
y *= node_.y;
ctx.fillRect(x + 1, y + 1, w - 2, w - 2);
});
任务是以尽可能快的方式从这些节点中构建一棵树,以获得如下内容:
var result = [
{id: "0.1", children: null },
{id: "0.2", children: null },
{id: "0.3", children: null },
{id: "0.4", children: [
{ id: "0.1.1", children: [
...
] },
{ id: "0.1.2", children: [] },
{ id: "0.1.3", children: [] },
{ id: "0.1.4", children: [] },
] }
];
更新:
ID 是通过这个逻辑生成的——左上角是 1,右上角是 2,左下角是 3,右下角是 4。
所以,即底部左边的绿色方块是4.3,它右边的邻居是4.4。 第一个洋红色正方形是 4.1.1。
在初始 1D 数组级别中,x 和 y 值负责定位和缩放分区,因此您始终可以通过这些值获取其级别和父级。
我只需要使用这些级别、x 和 y 值将 1D 数组转换为 2D 树。
我正在尝试理解并构建它,我有一个似乎可行的解决方案,但要求级别不要“跳跃”(即连续),所以在您的示例中,没有级别 3,这有效吗? 我创建了一个稍微简化的示例来展示这如何适用于连续级别:
const colors = ["#FF0000", "#00FF00", "#0000FF", "#FF00FF", "#00FFFF"]; const array1D = [ { level: 1, x: 0, y: 0 }, { level: 1, x: 16, y: 0 }, { level: 1, x: 0, y: 16 }, //* //* { level: 3, x: 16, y: 16 }, { level: 3, x: 20, y: 16 }, { level: 3, x: 16, y: 20 }, { level: 3, x: 20, y: 20 }, //*/ { level: 2, x: 24, y: 16 }, { level: 2, x: 16, y: 24 }, { level: 2, x: 24, y: 24 } //* ]; const arrayNested = createdNestedQuadTree(array1D); console.log(arrayNested); function createdNestedQuadTree(input, level) { const nestedOutput = []; //don't mutate input, call with shallow copy: innerRecursive([...input], nestedOutput); function innerRecursive(currArr, parentArr, level){ const currentLevel = level || 1; const currentChildren = []; const pointOfNesting = {}; for (let i of [1,2,3,4]){ const item = currArr[i-1]; //console.log(currentLevel, i, item); if (currentLevel == item.level){ item.id = `${currentLevel}.${i}`; item.children = null; parentArr.push(item); //console.log('output', nestedOutput); } else { pointOfNesting.id = `${currentLevel}.${i}`; pointOfNesting.children = []; parentArr.push(pointOfNesting); //console.log('parent', parentArr); let child = currArr[i-1]; let j = i - 1; let position = 1; //console.log(child); while (child && child.level > currentLevel){ //console.log('child', child); currentChildren.push(child); j +=1; child = currArr[j]; } currArr.splice(i-1, (j - (i-1) ) ); currArr.splice(i-1, 0, pointOfNesting); //console.log('curr', currArr); //console.log('parent', parentArr); //console.log('children', currentChildren); //console.log('output', nestedOutput); innerRecursive([...currentChildren], pointOfNesting.children, currentLevel + 1) } } } return nestedOutput; }
.as-console-wrapper { max-height: 100%;important: top; 0; }
Output:
[
{
"level": 1,
"x": 0,
"y": 0,
"id": "1.1",
"children": null
},
{
"level": 1,
"x": 16,
"y": 0,
"id": "1.2",
"children": null
},
{
"level": 1,
"x": 0,
"y": 16,
"id": "1.3",
"children": null
},
{
"id": "1.4",
"children": [
{
"id": "2.1",
"children": [
{
"level": 3,
"x": 16,
"y": 16,
"id": "3.1",
"children": null
},
{
"level": 3,
"x": 20,
"y": 16,
"id": "3.2",
"children": null
},
{
"level": 3,
"x": 16,
"y": 20,
"id": "3.3",
"children": null
},
{
"level": 3,
"x": 20,
"y": 20,
"id": "3.4",
"children": null
}
]
},
{
"level": 2,
"x": 24,
"y": 16,
"id": "2.2",
"children": null
},
{
"level": 2,
"x": 16,
"y": 24,
"id": "2.3",
"children": null
},
{
"level": 2,
"x": 24,
"y": 24,
"id": "2.4",
"children": null
}
]
}
]
对应于这个四叉树(32 x 32):
这是一个更复杂的示例(但又是连续的):
const colors = ["#FF0000", "#00FF00", "#0000FF", "#FF00FF", "#00FFFF"]; const array1D = [ { level: 1, x: 0, y: 0 }, { level: 1, x: 16, y: 0 }, { level: 1, x: 0, y: 16 }, //* <level 2> //* <level 3> { level: 3, x: 16, y: 16 }, //* <level 4> { level: 4, x: 20, y: 16 }, //* <level 5> { level: 5, x: 22, y: 16 }, { level: 5, x: 23, y: 16 }, { level: 5, x: 22, y: 17 }, { level: 5, x: 23, y: 17 }, //*/ </level 5> { level: 4, x: 20, y: 18 }, { level: 4, x: 22, y: 18 }, //*/ </level 4> { level: 3, x: 16, y: 20 }, { level: 3, x: 20, y: 20 }, //*/ </level 3> { level: 2, x: 24, y: 16 }, { level: 2, x: 16, y: 24 }, { level: 2, x: 24, y: 24 } //* </level 2> ]; const arrayNested = createdNestedQuadTree(array1D); console.log(arrayNested); function createdNestedQuadTree(input, level) { const nestedOutput = []; //don't mutate input, call with shallow copy: innerRecursive([...input], nestedOutput); function innerRecursive(currArr, parentArr, level){ const currentLevel = level || 1; const currentChildren = []; const pointOfNesting = {}; for (let i of [1,2,3,4]){ const item = currArr[i-1]; //console.log(currentLevel, i, item); if (currentLevel == item.level){ item.id = `${currentLevel}.${i}`; item.children = null; parentArr.push(item); //console.log('output', nestedOutput); } else { pointOfNesting.id = `${currentLevel}.${i}`; pointOfNesting.children = []; parentArr.push(pointOfNesting); //console.log('parent', parentArr); let child = currArr[i-1]; let j = i - 1; let position = 1; //console.log(child); while (child && child.level > currentLevel){ //console.log('child', child); currentChildren.push(child); j +=1; child = currArr[j]; } currArr.splice(i-1, (j - (i-1) ) ); currArr.splice(i-1, 0, pointOfNesting); innerRecursive([...currentChildren], pointOfNesting.children, currentLevel + 1) } } } return nestedOutput; }
.as-console-wrapper { max-height: 100%;important: top; 0; }
Output:
[
{
"level": 1,
"x": 0,
"y": 0,
"id": "1.1",
"children": null
},
{
"level": 1,
"x": 16,
"y": 0,
"id": "1.2",
"children": null
},
{
"level": 1,
"x": 0,
"y": 16,
"id": "1.3",
"children": null
},
{
"id": "1.4",
"children": [
{
"id": "2.1",
"children": [
{
"level": 3,
"x": 16,
"y": 16,
"id": "3.1",
"children": null
},
{
"id": "3.2",
"children": [
{
"level": 4,
"x": 20,
"y": 16,
"id": "4.1",
"children": null
},
{
"id": "4.2",
"children": [
{
"level": 5,
"x": 22,
"y": 16,
"id": "5.1",
"children": null
},
{
"level": 5,
"x": 23,
"y": 16,
"id": "5.2",
"children": null
},
{
"level": 5,
"x": 22,
"y": 17,
"id": "5.3",
"children": null
},
{
"level": 5,
"x": 23,
"y": 17,
"id": "5.4",
"children": null
}
]
},
{
"level": 4,
"x": 20,
"y": 18,
"id": "4.3",
"children": null
},
{
"level": 4,
"x": 22,
"y": 18,
"id": "4.4",
"children": null
}
]
},
{
"level": 3,
"x": 16,
"y": 20,
"id": "3.3",
"children": null
},
{
"level": 3,
"x": 20,
"y": 20,
"id": "3.4",
"children": null
}
]
},
{
"level": 2,
"x": 24,
"y": 16,
"id": "2.2",
"children": null
},
{
"level": 2,
"x": 16,
"y": 24,
"id": "2.3",
"children": null
},
{
"level": 2,
"x": 24,
"y": 24,
"id": "2.4",
"children": null
}
]
}
]
对应于这个四叉树(32 x 32):
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.