JS 数组与树形相互转换

JS 数组与树形相互转换

话不多说,直接上代码

首先来搞一个数据

let arr = [
            {id: 1, label: '1', parentId: -1,},
            {id: 2, label: '2', parentId: -1,},
            {id: 3, label: '1-1', parentId: 1,},
            {id: 4, label: '1-2', parentId: 1,},
            {id: 5, label: '2-1', parentId: 2,},
            {id: 6, label: '1-1-1', parentId: 3,},
        ];

数组 → 树形 方式一

这个方式没有用到 reduce 从 JS Array.reduce 理解与使用 的小伙伴请看 数组 → 树形 方式二

/**
 * 通过数组建造树形结构
 * @param array        {Array}  树形结构平面数组
 * @param id_key       {String} 树形 ID键名
 * @param parentId_key {String} 树形 父级ID 键名
 * @param isRoot     {Function} 回调函数,调用者需要实现该函数,函数结果应为 Boolean 类型
 *        回调时会将从数组中遍历的当前对象与该对象的父级对象一并返回
 *        调用者需要 return 当前对象是否是根节点
 * @return {[{}]} 树形结构
 */
function buildTree(array, id_key, parentId_key, isRoot) {
    if (!!!array) return tree;
    let idsObj = {}, tree = [];
    array.forEach(item => idsObj[item[id_key]] = item);
    Object.values(idsObj).forEach(item => {
        let parentId = item[parentId_key],
            parent = idsObj[parentId];
        if (!isRoot(item, parent)) {
            !!!parent.children && (parent.children = []);
            let children = parent.children;
            !children.includes(item) && children.push(item);
        } else {
            tree.push(item);
        }
    });
    return tree;
}
let tree = buildTree(arr, 'id', 'parentId', item => item.parentId === -1);
console.log(tree); //打印的就是树形结构了,我就偷个懒不截图了,两点钟了

数组 → 树形 方式二

使用 reduce 进行转换。什么?你还不会 reduce ? 我教你呀!点我学习

/**
 * 通过数组建造树形结构
 * @param array        {Array}  树形结构平面数组
 * @param id_key       {String} 树形 ID键名
 * @param parentId_key {String} 树形 父级ID 键名
 * @param isRoot     {Function} 回调函数,调用者需要实现该函数,函数结果应为 Boolean 类型
 *        回调时会将从数组中遍历的当前对象与该对象的父级对象一并返回
 *        调用者需要 return 当前对象是否是根节点
 * @return {[{}]} 树形结构
 */
function buildTree2(array, id_key, parentId_key, isRoot) {
    if (!!!array) return [];
    let idsObj = array.reduce((pre, cur) => Object.assign(pre, {[cur[id_key]]: cur}), {});
    return Object.values(idsObj).reduce((pre, cur) => {
        let parent = idsObj[cur[parentId_key]];
        if (!isRoot(cur, parent)) {
            !!!parent.children && (parent.children = []);
            let children = parent.children;
            !children.includes(cur) && children.push(cur);
        } else {
            pre.push(cur);
        }
        return pre
    }, []);
}
let tree2 = buildTree2(arr, 'id', 'parentId', item => item.parentId === -1);

树形 → 数组 方式一

这个方式没有用到 reduce 从 JS Array.reduce 理解与使用 的小伙伴请看 树形 → 数组 方式二

/**
 * 拆解树为数组,并且不会对原始对象进行修改,原始对象子集列表也不会进行删除。
 * @param tree          {Array}          树形数组
 * @param children_key  {String}         子集对象 'key'
 * @return {[{}]} 树形被拆解后的数组
 */
function untieTree(tree, children_key='children') {
    if(!!!tree || Object.prototype.toString.call(tree) !== '[object Array]' || tree.length<=0) return [];
    const temp = [];
    tree.forEach(item => {
        temp.push(item, ...untieTree(item[children_key], children_key))
    });
    return temp;
}
console.log(untieTree(tree));   //这个 tree 是通过刚才上面 数组 → 树形 得到的,不想打结构了,偷个懒
//这里拆解树出来的结果就是数组了,我就截图了,偷个懒,两点了

树形 → 数组 方式二

使用 reduce 进行转换。什么?你还不会 reduce ? 我教你呀!点我学习

/**
 * 方式二 使用 reduce 函数
 * 拆解树为数组,并且不会对原始对象进行修改,原始对象子集列表也不会进行删除。
 * @param tree          {Array}          树形数组
 * @param children_key  {String}         子集对象 'key'
 * @return {[{}]} 树形被拆解后的数组
 */
function untieTree2(tree, children_key='children') {
    if(!!!tree || Object.prototype.toString.call(tree) !== '[object Array]' || tree.length<=0) return [];
    return tree.reduce((pre, cur) => pre.concat(cur, untieTree2(cur[children_key], children_key)), []);
}
console.log(untieTree2(tree));  //这个 tree 是通过刚才上面 数组 → 树形 得到的,不想打结构了,偷个懒

要不要看看我的
多维数组怎么拍平扁平化处理?

你可能感兴趣的:(JS 数组与树形相互转换)