现有一个一维数组 对应 学校 班级 学生
let inputArr = [
{ id: 2, val: "班级1", parentId: 1, },
{ id: 4, val: "班级3", parentId: 1, },
{ id: 5, val: "学生1", parentId: 2, },
{ id: 1, val: "学校", },
{ id: 6, val: "学生2", parentId: 3 },
{ id: 3, val: "班级2", parentId: 1, },
{ id: 7, val: "学生3", parentId: 4 },
];
需要转换成 :
let output = { id: 1, val: "学校", children: [ {id: 2, val: "班级1", children: [{ id: 5, val: "学生1"}]}, {id: 3, val: "班级2", children: [{ id: 6, val: "学生2"}], }, {id: 4, val: "班级3", children: [{ id: 7, val: "学生3"}], }, ],};
解决方案:
function getTreeArr(floatArr) {
if (!Array.isArray(floatArr)) throw new Error('参数错误')
const float = JSON.parse(JSON.stringify(floatArr))//深拷贝数组 注意json的局限性
const result = []
const map = {}//储存对象数组 使用浅拷贝引用地址指向同一目标的特性
//最开始使用的是 new Map()数据结构 所以对象名取map 实际效果差不多
float.forEach(item => {
item.children = []
!map[item.id] && (map[item.id] = item)//将数据拷贝进对象里面
})
float.forEach(item => {
if (map[item.parentId]) {//父id对应id
map[item.parentId].children.push(item)//浅拷贝的引用地址
}
!item.parentId && result.push(item)//没有父id的是最上层数据添加进结果数组
})
return result
}
console.log(getTreeArr(inputArr), inputArr);
//此题是 parentId对应id .扩展一下 可以给函数新增两个参数 用于对应关系
//还可以新增一个回调参数 做其他用处
比较老土的回调函数写法
function splitArr(arr) {
let result = []
arr.forEach(i => {
if (!i.parentId) result.push(i) //先添加初始值 没有parentId
})
const parentIdArr = [...new Set(arr.map(i => i.parentId))] //提取parentId,去重
function inside(filterArr, pid) {
const _result = filterArr.filter(item => item.parentId === pid).map(i => {
delete i.parentId
return i
}) //过滤出来一个数组,这就是需要的数据,但是还需要挂载子数组
const newArr = filterArr.filter(function (obj1, index) { //过滤掉已经使用的数组,剩下还没有分配的数组
return !_result.find(function (obj2) {
return obj1.id === obj2.id
})
})
const _parentIdArr = [...new Set(newArr.map(i => i.parentId))]
_parentIdArr.length && _result.forEach(item => { //剩下的数组还有内容就继续执行
if (_parentIdArr.some(i => i === item.id)) { //如果有检测到父id就执行一次回调函数
item.children = inside(newArr, item.id)
}
})
return _result
}
result.forEach(item => {
if (parentIdArr.some(i => i === item.id)) { //如果父id数组有,就调用这个方法
item.children = inside(arr.filter(i => i.parentId), item.id)
}
})
return result.length === 1 ? result[0] : result
}
console.log(splitArr(inputArr));