将有层级标志的数组转为树状结构

本文介绍了如何将包含层级信息的数组转换为树状结构,特别是处理菜单数据。通过两次循环实现的方法是先将一级菜单放入数组,其余放入另一个数组,并用ID作为键存储。然后在第二次循环中,根据parentId找到父级并将其添加到父级的children中。然而,通过一次循环也能完成转换,关键在于处理子级先出现的情况,创建临时父级并在真正的父级出现时进行替换。详细代码展示了一次性转换的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目中遇到了将数组形式的菜单转化为树状结构的菜单

例如,原始数据是

 

[
    {id: 1,  parentId: 0, name: '第一级菜单A' },
    {id: 2,  parentId: 0, name: '第一级菜单B' },
    {id: 3,  parentId: 1, name: '第二级菜单A' },
    {id: 4,  parentId: 1, name: '第二级菜单B' },
    {id: 5,  parentId: 3, name: '第三级菜单A' },
    {id: 6,  parentId: 3, name: '第三级菜单B' },
    {id: 7,  parentId: 4, name: '第三级菜单C' },
    {id: 8,  parentId: 4, name: '第三级菜单D' },
    {id: 9,  parentId: 2, name: '第二级菜单C' },
    {id: 10, parentId: 2, name: '第二级菜单D' }
]

 转化为

 

  

 

 

需求已经明确,现在就看是怎么实现的

 

两次对数组两次循环

第一次循环

    找到所有第一级菜单放入数组A,其余的放入另一个数组B,并将所有菜单以id作为key放入一个对象C中,

第二次循环

    对数组B循环,通过parentId到对象C中找到父级,并push到父级的children数组中。

通过这两次循环,已经转化完成,代码如下

 

function array2tree (arr) {
    var top = [], sub = [], arrObj = {};

    arr.forEach(function (item) {
        if (item.parentId === 0) {
            top.push(item);
        } else {
            sub.push(item);
        }
        item.children = [];
        arrObj[item.id] = item;
    });

    sub.forEach(function (item) {
        var parent = arrObj[item.parentId] || {'children': []};
        parent.children.push(item);
    });

    return top;
}

 

 

那么问题来了,能否通过一次循环就解决问题,答案是可以的

在循环过过程中将第一级菜单放入数组A,将所有菜单以id作为key放入对象B中,同时以parentId作为key在对象B中找到其父级,并将其push到父级的children中,在这一步需要注意的是,如果子级先出现,那么就有可能在对象B中找不到父级。所以这里要作点处理,具体如下

如果子级先出现,在对象B中找不到父级,这是要在对象B中创建一个对象作为临时的父级,并将子级push到这个临时的父级children中。当然这个子菜单也要放入对象B中

这是又会出现另外一个问题,当真正的父级出现时,对象B中已经存在一个临时的父级时,这时要作的处理是将临时的父级的属性扩展到真正的父级中,并用真正的父级替换对象B中的临时父级。

 

哈哈,真绕,看代码

function array2tree (arr) {
    var top = [], arrObj = {};

    arr.forEach(function (item) {
        var id = item.id, parentId = item.parentId, parent, own;
        if (parentId === 0) {
            top.push(item);
        }

        item.children = [];
        own = arrObj[id];
        if (own) {
            Object.keys(own).forEach(function (key) {
                item[key] = own[key];
            });
        }
        arrObj[id] = item;

        parent = arrObj[parentId];
        if (!parent) {
            parent = {'id': parentId, 'children': []};
            arrObj[parentId] = parent;
        }
        parent.children.push(item);

    });
    return top;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值