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 是通过刚才上面 数组 → 树形 得到的,不想打结构了,偷个懒
要不要看看我的
多维数组怎么拍平扁平化处理?