美文网首页
JS 树结构数据各种递归

JS 树结构数据各种递归

作者: Cherry丶小丸子 | 来源:发表于2021-02-04 14:49 被阅读0次
递归-----树组件节点属性修改
参数为数组

/**
 * 递归-----树组件节点属性修改
 * @param {Object} data       树的源数据
 * @returns {Object} data     属性修改后的树的数据
 */
setTreeRecursion(data) {
    data.map((item, index) => {
        item.scopedSlots = { title: 'customNode' };
        if(item.children && item.children.length != 0){
            this.setTreeRecursion(item.children);
        }
    });
    return data;
}
setTreeRecursion('树结构数据')
参数为对象

/**
 * 递归-----树组件节点属性修改
 * @param {Object} data       树的源数据
 * @returns {Object} data     属性修改后的树的数据
 */
setTreeRecursion(data) {
    data.scopedSlots = { title: 'customNode' };
    if(data.children && data.children.length != 0){
        data.children.map((item, index) => {
            this.setTreeRecursion(item);
        });
    }
    return data;
}
setTreeRecursion('树结构数据')
递归-----查询 树组件 共有多少节点
参数为数组

/**
 * 递归-----查询 树组件 共有多少节点
 * @param {Object}      data树的源数据
 * @returns {Number}    num 总节点数
 */
queryNodesTotal(data, num = 0){
    let forFn = nodes => {
        for(let i = 0; i < nodes.length; i++){
            num++;
            if(nodes[i].children && nodes[i].children.length != 0){
                forFn(nodes[i].children);
            }
        }
    }
    forFn(data);
    return num;
}
queryNodesTotal('树结构数据')
参数为对象

/**
 * 递归-----查询 树组件 共有多少节点
 * @param {Object}      data树的源数据
 * @returns {Number}    num 总节点数
 */
queryNodesTotal(data, num = 0){
    let forFn = nodes => {
        num++;
        if(nodes.children && nodes.children.length != 0){
            for(let i = 0; i < nodes.children.length; i++){
                forFn(nodes.children[i]);
            }
        }
    }
    forFn(data);
    return num;
}
queryNodesTotal('树结构数据')

递归-----取出树组件最后子节点
/**
 * 递归-----取出树组件最后子节点---对象
 * @param {Object} node      树的源数据
 * @returns {Object} temp    取出树组件最后子节点的集合
 */
getLastChildNode(node, temp = []) {
    let forFn = (arr) => {
        for (let i = 0; i < arr.length; i++) {
            if (!arr[i].children || arr[i].children.length == 0) {
                temp.push(arr[i]);
            } else {
                forFn(arr[i].children);
                // if(arr[i].children && arr[i].children.length != 0){
                    // forFn(arr[i].children);
                // }
            }
        }
    }
    forFn(node)
    return temp;
}
getLastChildNode('树结构数据')
/**
 * 递归-----取出树组件最后子节点---数组
 * @param {Object} node      树的源数据
 * @returns {Object} temp    取出树组件最后子节点的集合
 */
getLastChildNode(node, temp = []) {
    let forFn = (arr) => {
        for (let i = 0; i < arr.length; i++) {
            if (!arr[i].children || arr[i].children.length == 0) {
                temp.push(arr);
                arr = [];
            } else {
                forFn(arr[i].children);
            }
        }
    }
    forFn(node)
    return temp;
}
getLastChildNode('树结构数据')
递归-----删除树组件源数据的最后子节点
/**
 * 递归-----删除树组件源数据的最后子节点
 * @param {Object} node      树的源数据
 * @returns {Object} node    删除最后子节点之后的树的数据
 */
deleteSourceNode(node) {
    for (let i = node.length - 1; i >= 0; i--) {
        if (!node[i].hasOwnProperty('children')) {
            continue;
        }
        if (!node[i].children || node[i].children.length == 0) {
            node.splice(i, 1);
            continue;
        }
        this.deleteSourceNode(node[i].children);
    }
    return node;
}
deleteSourceNode('树组件数据')
递归-----根据 id 查询当前节点 或者 根据 pId 查询当前节点的父节点 或者 所有父级点集合
/**
 * 递归-----根据 id 查询当前节点 或者 根据 pId 查询当前节点的父节点
 * @param node      树的源数据
 * @param nodeId    节点的 id 或者 pId
 * @returns temp    返回的匹配的节点数据
 */
queryNodeById(node, nodeId, temp = {}){
    let forFn = (arr, id) => {
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].id === id) {
                temp = arr[i]; // 匹配到的节点 或者 父节点
                break;
            } else {
                if (arr[i].children && arr[i].children.length != 0) {
                    forFn(arr[i].children, id);
                }
            }
        }
    }
    forFn(node, nodeId);
    return temp;
}
queryNodeById('树组件数据', '节点的 id 或者 pId')
/**
 * 递归-----根据 根据 pId 查询当前节点的 所有父级点集合
 * @param node      树的源数据
 * @param pId       节点的 pId
 * @returns temp    返回的匹配的节点数据
 */
queryNodeById(node, pId, temp = []){
    let forFn = (arr, id) => {
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].id === id) {
                temp.push(arr[i]); // 匹配到的节点 push 到 temp 中
                forFn(node, arr[i].pId); // 继续递归查询
                break;
            } else {
                if (arr[i].children && arr[i].children.length != 0) {
                    forFn(arr[i].children, id);
                }
            }
        }
    }
    forFn(node, pId);
    return temp;
}
queryNodeById('树组件数据', '节点的 pId')

`此方法也可以的第二个参数也可以传入 节点的 id,如果传入的是 id, 则返回的是包含此节点以及所有父级节点

如果传入的仅是此节点的 pId,返回的是不包含此节点的所有父级节点`
/**
 * 递归-----根据 id 查询当前节点 和 根据 pId 查询 当前节点的所有父级节点集合
 * @param node      树的源数据
 * @param nodeId    节点的 id
 * @param nodePid   节点的 pId
 * @param temp      返回的匹配的节点数据集合
 * @returns {{pNodes: *[], cNode: {}}} pNodes: 父级节点集合,cNode:当前节点
 */
queryNodeById(node, nodeId, nodePid, temp = {cNode: {}, pNodes: []}){
    let forFn = (arr, id, pId) => {
        for (let i = 0; i < arr.length; i++) {

            if (arr[i].id === id) {
                temp.cNode = arr[i];
                break;
            }else if (arr[i].id === pId) {
                temp.pNodes.push(arr[i]);
                forFn(node, id, arr[i].pId);
                break;
            } else {
                if (arr[i].children && arr[i].children.length != 0) {
                    forFn(arr[i].children, id, pId);
                }
            }

        }
    }
    forFn(node, nodeId, nodePid);
    return temp;
}

queryNodeById('树组件数据', '节点的 id', '节点的 pId')

上述 三种方法,都是获取当前节点以及父级节点的方法,如果想要获取当前节点以及子级节点,可以按照上边的方法自行修改

递归-----树形数据(数组)获取最深层级数
/**
 * 递归-----树形数据(数组)获取最深层级数
 * @param {Object} treeData   树的源数据
 * @returns {Number} max      最深层级数的值
 */
getMaxFloor(treeData) {
    let floor = 0;
    let max = 0;
    let deepEach = (data, floor) => {
        data.map((item, index) => {
            item.floor = floor;
            if (floor > max) {
                max = floor;
            };
            if (item.children && item.children.length != 0) {
                deepEach(item.children, floor + 1);
            };
        });
    };
    deepEach(treeData, 1);
    return max;
}
getMaxFloor('树组件数据')
递归-----将树结构数据格式,转化为 二维数组 表格形式
node 参数为 数组

/**
 * 递归-----将树结构数据格式,转化为 二维数组 表格形式
 * @param node  树的源数据
 * @param data  树转化为二维数组的数据
 * @param row   临时存储数据
 * @returns {*[]}
 */
parseTreeToRow(node, data = [], row = []) {
    node.map(item => {
        let obj = {
            id: item.id,
            pId: item.pId,
            label: item.label
        }
        if(item.children && item.children.length != 0){
            this.parseTreeToRow(item.children, data, [...row, obj]);
        }else{
            data.push([...row, obj])
        }
    })
    return data;
}

this.parseTreeToRow('树的源数据---数组');
node 参数为 对象

/**
 * 递归-----将树结构数据格式,转化为 二维数组 表格形式
 * @param node  树的源数据
 * @param data  树转化为二维数组的数据
 * @param row   临时存储数据
 * @returns {*[]}
 */
parseTreeToRow(node, data = [], row = []) {
    if (node.children && node.children.length != 0) {
        node.children.map((item, index) => {
            const obj = {
                id: item.id,
                pId: item.pId,
                label: item.label,
            };
            this.parseTreeToRow(item, data, [...row, obj]);
        });
    } else {
        data.push(row);
    }
    return data;
}

// 需要一个有且只有一个根节点的数据
let obj = {
    id: '',
    pId: '',
    label: '',
    children: '树组件数据'
}
this.parseTreeToRow(obj);
递归----- tree 转 一维数组
/**
 * 递归----- tree 转 一维数组
 * @param treeData
 * @param arr
 * @returns {*[]}
 */
treeToArr(treeData = [], arr = []) {
    for (let item of treeData) {
        arr.push(item);
        if (item.children && item.children.length != 0) {
            this.treeToArr(item.children, arr);
        }
    }
    return arr;
},
递归----- 一维数组 转 tree
/**
 * 递归----- 一维数组 转 tree (此方法会改变原始数组 data,使用时请注意)
 * @param {Object} data 一维数组
 * @param {Object} pId 最外层父 id (一般为 0)
 */
arrayToTree(data, pId) {
    let tree = [];
    let temp;
    for (let i = 0; i < data.length; i++) {
        if (data[i].pId == pId) {
            let obj = data[i];
            temp = this.arrayToTree(data, data[i].id);
            if (temp.length > 0) {
                obj.children = temp;
            }
            tree.push(obj);
        }
    }
    return tree;
}

let data = [
    { id: '1', pId: '0', label: "一级菜单-1" }, 
    { id: '1-2', pId: '1', label: "二级菜单-1-2" },
    { id: '1-3', pId: '1-2', label: "三级菜单-1-3" },
    { id: '1-4', pId: '1-3', label: "四级菜单-1-4" },

    { id: '2', pId: '0', label: "一级菜单-2" },
    { id: '2-1', pId: '2', label: "二级菜单-2-1" },
    { id: '2-1-1', pId: '2-1', label: "三级菜单-2-1-1" },
    { id: '2-1-2', pId: '2-1', label: "三级菜单-2-1-2" }
];

// 调用
arrayToTree(data, '0');
递归-----根据特定数组 匹配 tree 数据,仅保留匹配项
let brr = ['1', '2', '3']
let arr = [
    {
        id: '1',
        pid: '0',
        name: '1',
        children: [
            {
                id: '1-1',
                pid: '0',
                name: '1-1',
                children: []
            }
        ]
    },
    {
        id: '2',
        pid: '0',
        name: '2',
        children: []
    },
    {
        id: '3',
        pid: '0',
        name: '3',
        children: []
    }
];

/**
 * 递归-----根据特定数组 匹配 tree 数据,仅保留匹配项
 * @param localRoute 第一个比较的数组
 * @param returnRoute 第二个比较的数组
 * @returns {*}
 */
matchSpecialData(localRoute, returnRoute) {
    for (let i = 0; i < localRoute.length; i++) {
        if(localRoute[i].children && localRoute[i].children.length != 0){
            this.matchSpecialData(localRoute[i].children, returnRoute);
        }
        let flag = false;
        for(let j = 0; j < returnRoute.length; j++){
            if(localRoute[i].name == returnRoute[j]){
                flag = true;
                break;
            }
        }
        if(!flag){
            localRoute.splice(i--, 1);
        }
    }
    return localRoute;
}

this.matchSpecialData(arr, brr);

相关文章

网友评论

      本文标题:JS 树结构数据各种递归

      本文链接:https://www.haomeiwen.com/subject/dvjbtltx.html