已知原有数据 :
var data=[
{ id: 40, parentId: 31, note: "的萨达是" },
{ id: 20, parentId: 11, note: "的萨达是" },
{ id: 22, parentId: 20, note: "dsadas" },
{ id: 12, parentId: null, note: "dsadasad萨达s" },
{ id: 11, parentId: undefined, note: "dqwds" },
{ id: 24, parentId: 22, note: "搜索" },
{ id: 34, parentId: 22, note: "搜索" }
]
需要考虑的问题 :
不更改源数据
避免循环引用, 即 a的parentId为b, b的parentId为a
发挥你的大脑, 来个最优解
回答
先来个函数注释 :
/**
* 将有父子关系的一维数组转换成树形结构(多维)数据
* console.log(JSON.stringify(setTreeData(data), null, 2));
* ============================================
* @param {*Array} data 需要遍历的一维数组
*/
再来具体的代码 :
function fnSetTreeData(data) {
var data = [...data];
var tree = data.filter((father) => {
var branchArr = data.filter((child) => {
if (father.id == child.parentId) child._hasParent = true;
return father.id == child.parentId;
// MARK 为什么这样写就报错 ?
// if (father.id == child.parentId) child._hasParent = true;
// return child._hasParent
});
if (branchArr.length > 0) father.children = branchArr;
return !father._hasParent;
});
// MARK 为什么在这里还得加一个过滤
tree = tree.filter((item) => {
return !item._hasParent;
})
return tree
}
console.log(JSON.stringify(fnSetTreeData(data), null, 2));
至于怎么解决 循环引用 的问题, 先用 sort 给数组排序后, 再在每次filter 中 计数++如何 ?
得给一个测试数据 :
var data = [
{ id: 40, parentId: 31, note: "的萨达是" },
{ id: 20, parentId: 11, note: "的萨达是" },
{ id: 22, parentId: 20, note: "dsadas" },
{ id: 12, parentId: null, note: "dsadasad萨达s" },
{ id: 11, parentId: undefined, note: "dqwds" },
{ id: 24, parentId: 22, note: "搜索" },
{ id: 34, parentId: 22, note: "搜索" }
];
const toTree =
(arr, pID) =>
arr
.filter(({ parentId }) => parentId == pID)
.map(a => ({
...a,
childers: toTree(arr.filter(({ parentId }) => parentId != pID), a.id)
}))
function listToTree(data) {
let arr = JSON.parse(JSON.stringify(data))
const listChildren = (obj, filter) => {
[arr, obj.children] = arr.reduce((res, val) => {
if (filter(val))
res[1].push(val)
else
res[0].push(val)
return res
}, [[],[]])
obj.children.forEach(val => {
if (arr.length)
listChildren(val, obj => obj.parentId === val.id)
})
}
const tree = {}
listChildren(tree, val => arr.findIndex(i => i.id === val.parentId) === -1)
return tree.children
}
先复制一份原数组 为了不循环引用和增加循环效率 每往tree里加个节点 从复制数组里删掉此节点
我是来学习的,
这样子写好像也是能实现的,但是不友好。希望各位提建议。
双层循环,外层循环的id匹配内层循环的parentId,相等的话内层循环的item直接插入外层循环item的childers中,
内层循环结束后外层循环判断自己的parentId是否匹配得到,匹配不到单独拎出来。
function setTreeData(arg) {
var data = [...arg];
var sort = [];
var parentIdArr = []
data.map((item, idx) => {
item.childers = [];
let pp = Object.assign({}, data)
data.map((subitem, subidx) => {
parentIdArr.push(subitem.id)
if (item.id === subitem.parentId) {
item.childers.push(subitem);
}
})
var obj = Object.assign({}, item);
parentIdArr = [...new Set(parentIdArr)]
if (item.parentId - 1 > 0) {
parentIdArr.indexOf(item.parentId) == -1 ? sort.push(item) : ""
} else {
sort.push(item)
}
})
return sort
}