数组结构转树型结构

2022-02-25 19:28:08 浏览数 (1)

数组转树

代码语言:javascript复制
var tree1 = [{
        "p_id": 0,
        "id": 33,
        "name": "港澳",
    },
    {
        "p_id": 33,
        "id": 3477,
        "name": "香港特别行政区",
    },
    {
        "p_id": 33,
            "id": 3478,
        "name": "澳门特别行政区",
    },
    {
        "p_id": 3477,
        "id": 3502,
        "name": "九龙城区"
    },
    {
        "p_id": 0,
        "id": 6,
        "name": "辽宁省",
    },
    {
        "p_id": 6,
        "id": 645,
        "name": "抚顺市"
    },
]

递归1

代码语言:javascript复制
/**
 * 性能最差,全部递归。
 * 思想:把所有数据都当成子层,传入一个pid,获取所有id等于pid的数据,
 * 且当id等于pid时,先获取当前项的所有children,获取到当前项的所有children后,
 * 再将该项连同获取到的children存到res里,当遍历完了后,就可以获取所有指定pid的树型数据,最后返回res
 */
function toTree(arr, pid) {
    // 循环,获取该id的children
    function loop(pid) {
        // 保存得到的数据
        var res = [];
        // 遍历原数组
        for (var i = 0; i < arr.length; i  ) {
            var item = arr[i]
            if (item.p_id === pid) {
                // 如果遍历到当前item的p_id等于目标pid,在将该item插入到res前,
                // 先遍历该item的id,找到原数组arr里面该item的所有children后,再将该item连同找到的children一起插入到res
                item.children = loop(item.id)
                // 如果当前item的p_id等于目标pid,则将这个item插入res
                res.push(item)
            }
        }
        return res
    }

    return loop(pid)
}
console.log(toTree(tree, 0));

递归2

代码语言:javascript复制
/**
 * 第一次:传入tree以及父id:0,即找出tree里面所有父id是0的树型结构数据,
 * 进入for循环,第一次找到了港澳,港澳的id是33,
 * 再次重新遍历,找出tree里面所有p_id等于33的数据,
 * 遍历数据,首先找到香港的p_id是等于33,此时,不要直接将香港给港澳的children,
 * 而是先找香港的所有子,香港的id是3477,因此遍历所有数据,找到了九龙的p_id是3477,
 * 然后再找九龙的所有子,九龙的id是3502,遍历所有数据,找不到p_id是3502的数据,
 * 因此代表九龙下面没有子了,回到九龙的p_id,即香港,将九龙放到香港的children里,
 * 然后再次遍历继续找香港下面的子,但是找不到香港的子了,因此香港的数据找完了,将香港插入港澳的children,
 * 然后再次遍历,找到澳门的p_id等于33,此时,也是不要直接将澳门给港澳的children,
 * 而是先找到澳门的所有子,澳门的id是3478,因此遍历所有数据,找不到p_id是3478的数据,
 * 因此代表澳门下面没有子,将澳门插入港澳的children,
 * 最后继续遍历,找不到p_id是33的数据了,就把香港和澳门插入到港澳下面的children
 * 开始进入第二次遍历,找到澳门,其实澳门遍历过了,优化的时候要将遍历过的数据删掉
 * 优化后,第二次找到的应该是辽宁,辽宁的id是6,遍历当前数据(已经遍历过的已经删了),
 * 找出里面所有p_id等于6的数据,找到抚顺市的p_id是6,此时,不要直接将抚顺给辽宁的children,
 * 而是先找抚顺的所有子,抚顺的id是645,因此遍历当前数据,找不到id是645的数据,即代表
 * 抚顺没有子,继续找出p_id等于6的数据,遍历后没有找到数据,代表辽宁省数据找完了,
 * 将抚顺插入到辽宁省,
 * 开始进入第三次遍历,但是这时候已经遍历完了(因为遍历过的都被删了)
 * 最后返回修改后的数组
 */
function formatTree(arr) {
    // 因为数组里面的是对象(引用),因此为了不改变原数组最好先深拷贝一下
    var _arr = JSON.parse(JSON.stringify(arr))
    var _parent = _arr.filter(item => item.p_id == 0);
    var _children = _arr.filter(item => item.p_id != 0);
    var all = arr.filter(item => true)

    toTree(_parent, _children)

    function toTree(parent, children) {
        parent.map(p => {
            children.map((c, index) => {
                if (p.id == c.p_id) {
                    // 如果当前父id等于子pid,则先递归找到子的所有子,然后再插入到父里面
                    _children = JSON.parse(JSON.stringify(children))
                    // 每次遍历一个就删掉一个,以免重复遍历
                    _children.splice(index, 1)
                    toTree([c], _children)
                    if (p.children) {
                        p.children.push(c)
                    } else {
                        p.children = [c]
                    }
                }
            })
        })
    }

    return _parent
}
console.log(formatTree(tree1));

非递归

代码语言:javascript复制
function formatTree1(arr) {
    // 因为数组里面的是对象(引用),因此为了不改变原数组最好先深拷贝一下
    var _arr = JSON.parse(JSON.stringify(arr))

    // 遍历所有数据
    var newarr = _arr.filter(p => {
        // 获取当前父数据的所有children
        var temp = _arr.filter(c => p.id == c.p_id)
        // var temp = arr.filter(c => p.id == c.p_id)   //错误写法,这样的话并不会将
        // 如果获取到了有children,则将该children给父
        temp.length && (p.children = temp)
        // 最后返回这个p
        return p.p_id == 0
    })
    return newarr
}
console.log(formatTree1(tree1));
/**
 * 思想:将每一项都当作父,找他的子
 * 遍历第一个时,遍历所有数据,将属于他的children找出来,然后给添加到自己上面
 * 然后第二个遍历继续,遍历所有数据,将属于他的children找出来,然后给添加到自己上面
 * 直到遍历到最后一个(即遍历完所有数据)
 * 举例:tree1里面map先遍历第一个,第一个是港澳,港澳的p_id是0,遍历全部数据,找不到id是0的数据,
 * 继续遍历第二个,第二个是香港,香港的p_id是33,遍历全部数据,只找到港澳的id是33,将香港插入到港澳,
 * 继续遍历第三个,第三个是澳门,澳门的p_id是33,遍历全部数据,只找到港澳的id是33,将澳门插入到港澳,
 * 继续遍历第四个,第四个是九龙,九龙的p_id是3477,遍历全部数据,只找到香港的id是3477,将九龙插入到香港,
 * 注意,关键:这里遍历修改的都是原数组,一开始将香港的引用给了港澳,后面又将九龙给了香港,因此,这时的港澳里
 * 面除了一开始的香港和澳门,还有多一个九龙在香港里面
 * 后面的就跟上面的类似,不再继续写了
*/

0 人点赞