js处理数组扁平化、数组层级化

在项目中经常遇到需要处理后台给的数据情况,有的数据需要处理成树形结构进行展示,有的数据需要一维数组进行过滤

应用场景:

  1. 层级数据常用于层级节点的展示,例如Element的tree组件
  2. 扁平数据常用于权限过滤,例如: v-if=‘haha.incluedes(''heiehi")’

数据demo:

  1. 层级数据是有父子关系的数组,且子节点都会放到该节点的chilren下
  2. 扁平化数据是一个一维数组,里面可能有parentId标明该节点的父节点id
// 层级数据:
tree = [
    {
        id:1, name: 'hahha', chilren:[
            {id: 2, name: 'heiehi', chilren: []},
            {id: 3, name: 'heiehi2', chilren: []},
        ]
    },
    {
        id:4, name: 'hahha2', chilren:[
            {id: 5, name: 'heiehi3', chilren: []},
            {id: 6, name: 'heiehi4', chilren: []},
        ]
    }
]
// 扁平数据:
list = [
    { id:1, name: 'hahha' },
    { id:2, name: 'heiehi' },
    { id:3, name: 'heiehi2' },
    { id:4, name: 'hahha2' },
    { id:5, name: 'heiehi3' },
    { id:6, name: 'heiehi4' },
]

1、数组扁平化

数组扁平化是指把一个有层级结构的数据,处理成无层级的数据,简单来说就是把数据的children放到一维数据当中

处理方法:循环堆置为一个一维数组

树形结构数据扁平化处理方法比较简单,就是循环数据就可以了
下面用一个新思路迭代解决,原先利用递归处理方法比较简单:

  1. 循环tree,循环条件时tree的长度大于0(利用queen代表将要循环的数据)
  2. 当节点存在chilren(children的长度大于0)时,把chilren数据push到queen最后,这样queen的长度就更新了
  3. 循环时每次删除第一个数据进行处理,推送到out中(注意有children要删掉children)
  4. 这样处理就不需要用递归去处理了
// 方法1:递归
function treeToList(tree) {
    let arr = []
    for(item of tree) {
        if(item.children && item.children.length > 0){
            let sitem = { ...item }
            delete sitem.children
            arr = arr.concat(sitem, treeToList(item.children))
        } else {
            delete item.children
            arr.push(item)
        }
    }
    return arr
}
// 方法2:迭代
export function treeToList(tree) {
    var queen = []
    var out = []
    queen = queen.concat(tree)
    while(queen.length) {
        var first = queen.shift()
        if (first.children) {
            queen = queen.concat(first.children)
            delete first.children
        }
        out.push(first)
    }
    return out
}

可以看到递归消耗的时间几乎是迭代的两倍

2、数组层级化

// 方法1:
export function translateDataToTree(arr) {
    return arr.filter((father) => {
        let branchArr = arr.filter((child) => father.id == child.parentId)
        branchArr.length > 0 ? father.children = branchArr : ''
        return father.parentId == ''
    })
}
// 方法2:
export function translateDataToTree(arr) {
    let temp = {}
    let tree = {}
    arr = deepClone(arr)
    arr.forEach((item) => {
        temp[item.id] = item
    })
    let tempKeys = Object.keys(temp)
    tempKeys.forEach((key) => {
        let item = temp[key]
        let itemPId = item.parentId
        let parentItemByPid = temp[itemPId]
        if (parentItemByPid) {
            if (!parentItemByPid.children) {
                parentItemByPid.children = []
            }
            parentItemByPid.children.push(item)
        } else {
            tree[item.id] = item
        }
    })
    return Object.keys(tree).map((key) => tree[key])
}
// 方法3:
export function translateDataToTree(data, parentId = '') {
    let tree = []
    let temp
    data.forEach((item, index) => {
        if (data[index].parentId === parentId) {
            let obj = data[index]
            temp = translateDataToTree(data, data[index].id)
            if (temp.length > 0) {
                obj.children = temp
            }
            tree.push(obj)
        }
    })
    return tree
}

以下是时间对比,方法1和2差不多,方法3的时间明显较长,相比方法1慢了6.6倍多!!

 

方法1,2用于不同场景,可以看到方法1是按照接口给的顺序排序,而方法2则是根据id排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值