算法求助:无极树嵌套JSON数据转化为二维数组表格渲染

新手上路,请多包涵

原始数据:
{

"name": "我是爸爸",
"children": [
    {
        "name": "我是大儿子",
        "children": [
            {
                "name": "我是大儿子的儿子",
                "children": [
                    
                ]
            }
        ]
    },
    {
        "name": "我是二儿子",
        "children": [
            {
                "name": "我是二的大儿子",
                "children": [
                    
                ]
            },
            {
                "name": "我是二的二儿子",
                "children": [
                    
                ]
            }
        ]
    }
]

}
需求数据:
[

[
    {
        "name": "我是爸爸",
        "row": 3,
        "col": 1
    },{
        "name": "我是大儿子",
        "row": 1,
        "col": 1
    },{
        "name": "我是大儿子的儿子",
        "row": 1,
        "col": 1
    }
],
[
    {
        "name": "我是二儿子",
        "row": 2,
        "col": 1
    },{
        "name": "我是二的大儿子",
        "row": 1,
        "col": 1
    }
],
[
    {
        "name": "我是二的二儿子",
        "row": 1,
        "col": 1
    }
]

]
任意版本的js完成即可,最好不用es6,条件原因,部分不支持es6语法;

阅读 2.4k
3 个回答

用深度优先遍历来完成。

function treeToList (node, p = [], r = [], first = false) {
  let data = { name: node.name, col: 1, row: 1 }
  first ? r[r.length - 1].push(data) : r.push([data]) && p.forEach(n => n.row++)
  p.push(data)
  node.children && node.children.forEach((i, idx) => treeToList(i, p, r, !idx))
  p.pop()
  return r
}

测试一下:

console.log(treeTolist(data))

输出:

[
    [
        {
            "name":"我是爸爸",
            "col":1,
            "row":3
        },
        {
            "name":"我是大儿子",
            "col":1,
            "row":1
        },
        {
            "name":"我是大儿子的儿子",
            "col":1,
            "row":1
        }
    ],
    [
        {
            "name":"我是二儿子",
            "col":1,
            "row":2
        },
        {
            "name":"我是二的大儿子",
            "col":1,
            "row":1
        }
    ],
    [
        {
            "name":"我是二的二儿子",
            "col":1,
            "row":1
        }
    ]
]

没怎么测

      const data = {
        name: '我是爸爸',
        children: [
          {
            name: '我是大儿子',
            children: [
              {
                name: '我是大儿子的儿子',
                children: [],
              },
            ],
          },
          {
            name: '我是二儿子',
            children: [
              {
                name: '我是二的大儿子',
                children: [],
              },
              {
                name: '我是二的二儿子',
                children: [
                  {
                    name: '我是二的二儿子的1儿子',
                    children: [],
                  },
                ],
              },
            ],
          },
          {
            name: '我是3儿子',
            children: [
              {
                name: '我是3的1儿子',
                children: [
                  {
                    name: '我是3的1儿子的1儿子',
                    children: [],
                  },
                ],
              },
            ],
          },
        ],
      };

      /**
       * 获取最大层级 每个子树的尾节点 的 level 与 maxLevel 的差就是 cols
       */

      function getMaxLevel(node, level = 1) {
        if (!node.children.length) {
          if (level > maxLevel) {
            maxLevel = level;
          }

          return;
        }

        node.children.forEach((child) => getMaxLevel(child, level + 1));
      }

      function mark(node, level = 1) {
        if (!node.children.length) {
          node.rows = 1;
          node.cols = maxLevel - level + 1;

          return 1;
        }

        const rows = node.children.reduce(
          (total, item) => total + mark(item, level + 1),
          0
        );

        node.rows = rows;
        node.cols = 1;

        return rows;
      }

      function format(node) {
        return {
          name: node.name,
          rows: node.rows,
          cols: node.cols || 1,
        };
      }

      function chunk(node, ret, list = []) {
        list.push(format(node));

        node.children.forEach((child, index) => {
          // 第1个 以后的就不要 父级了
          const current = [...list.slice(index === 0 ? 0 : 1)];

          chunk(child, ret, current);
        });

        if (!node.children.length) {
          ret.push(list);
        }

        return list;
      }

      const ret = [];
      let maxLevel = -1;

      getMaxLevel(data);
      mark(data);
      chunk(data, ret);
      render(ret);

      function render(list) {
        const html = list
          .map(
            (coll) =>
              `<tr>${coll
                .map(
                  (item) => `<td colspan="${item.cols}" rowspan="${item.rows}" >
         ${item.name}
        </td>`
                )
                .join('')}</tr>`
          )
          .join('');

        const table = document.createElement('table');
        table.innerHTML = html;

        document.body.appendChild(table);
      }
新手上路,请多包涵

image.png

根据大佬的算法现在行和列是反的 诉求数据第一层总长度应该是34 然后里边的最大长度是4

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题