JS用filter实现List转Tree引发的思考

 原数组(在本例中顺序不影响结果)

let tree = [
    { id: 1, pid: 'root', name: '1' },
    { id: 2, pid: 1, name: '2' },
    { id: 3, pid: 1, name: '3' },
    { id: 4, pid: 'root', name: '4' },
    { id: 5, pid: 4, name: '4' },
    { id: 6, pid: 4, name: '5' },
    { id: 7, pid: 3, name: '7' },
    { id: 8, pid: 4, name: '8' },
]

 实现方法(使用filter实现)

function ListToTree(data) {
    // 简单对象的深度拷贝
    let cloneData = JSON.parse(JSON.stringify(data))

    // 两层嵌套的filter
    return cloneData.filter(father => {

        // 子结构分支 
        let branchArr = cloneData.filter(child => father['id'] == child['pid']);

        // console.log(`father key is ${father.id}`+JSON.stringify(branchArr)+"\n")

        branchArr.length > 0 ? father['children'] = branchArr : '';

        // 只需要返回根节点的元素
        return father['pid'] == 'root';
    })
}

//使用
let newTree = ListToTree(tree)
console.log(JSON.stringify(newTree));

引发的思考:两层filter循环应该只能处理两层树结构,但事实证明,这是多虑的。


进行测试:

console.log(`father key is ${father.id}`+JSON.stringify(branchArr)+"\n")

把ListToTree函数中的测试注释使用上,结果如下:

father key is 1 and branch is:[{"id":2,"pid":1,"name":"2"},{"id":3,"pid":1,"name":"3"}]

father key is 2 and branch is:[]

father key is 3 and branch is:[{"id":7,"pid":3,"name":"7"}]

father key is 4 and branch is:[{"id":5,"pid":4,"name":"4"},{"id":6,"pid":4,"name":"5"},{"id":8,"pid":4,"name":"8"}]

father key is 5 and branch is:[]

father key is 6 and branch is:[]

father key is 7 and branch is:[]

father key is 8 and branch is:[]

我们发现:

1.遍历到 father.id = 1 时,branch中的id=3子节点是没有children的;

2.遍历到 father.id = 3 时, 它才拥有了子节点(children数组) 

3.这似乎无济于事,因为第一步已经执行并返回了数组,结果就应该是只有两层树结构

4.根据结果来看,就算是第一步先执行并先返回,也会被后续的更改所影响


猜测:这时我们可以猜测这里的filter是对数组元素----对象的引用

证明:

let testItem = tree.filter(item=>{
    return item.id == 3
})
console.log(testItem[0] === tree[2])

结果:为True,所以他们的地址值相等,也就是filter返回的数组元素是对原数组元素中的地址的引用


至此我们也清楚了filter的原理以及如何将List转为Tree

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值