繁体   English   中英

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM