我遇到了从平面阵列构建树的问题。我正在建立一个类别 - >子类别树,其中父类具有子类别作为数组。
这是平面阵列的样子:
[
{
"id": 1
},
{
"id": 5,
},
{
"id": 2,
"parent_id": 1
},
{
"id": 3,
"parent_id": 1
},
{
"id": 42,
"parent_id": 5
},
{
"id": 67,
"parent_id": 5
}
]
这就是我需要的结果:
[
{
"id":1,
"subcategories":[
{
"id":2,
"parent_id":1
},
{
"id":3,
"parent_id":1
}
]
},
{
"id":5,
"subcategories":[
{
"id":42,
"parent_id":5
},
{
"id":67,
"parent_id":5
}
]
}
]
我试图通过递归搜索子项并将其作为数组附加来递归地执行此操作,并继续这样做,直到我击中桶的底部但我得到一个循环结构。似乎遍历中的parent_id始终是父级的id ...任何想法:
tree(passingInFlatObjectHere);
function topLevel (data) {
let blob = [];
data.forEach((each) => {
if (!each.parent_id) {
blob.push(each);
}
});
return blob;
}
function tree (data) {
let blob = topLevel(data).map(function (each) {
each.subcategories = traverse(data, each.id);
return each;
});
return blob;
}
function traverse (data, parent_id) {
let blob = [];
if (!parent_id) {
return blob;
}
data.forEach((each) => {
if (each.id === parent_id) {
each.subcategories = traverse(data, each.id);
blob.push(each);
}
});
return blob;
}
答案 0 :(得分:1)
我不仅希望帮助您解决问题,还希望帮助您充分利用ES6
首先,您的topLevel
函数可以重写为:
function topLevel(data) {
return data.filter(node => !node.parent_id);
}
整洁不是吗?我还建议稍微更改tree
以保持一致性,但这当然只是风格。
function tree(data) {
return topLevel(data).map(each => {
each.subcategories = traverse(data, each.id);
return each;
});
}
到目前为止还没有逻辑问题。但是,当您检查traverse
时,each.id === parent_id
包含一个。像这样,函数搜索id为parent_id
的节点。显然是个错误。你想要each.parent_id === parent_id
。
您的问题现已解决。如果我打扰你就停止阅读。但是你也可以在这里利用filter
并删除稍微多余的早期退出并将你的函数重写为:
function traverse(data, parentId) {
const children = data.filter(each => each.parent_id === parentId);
children.forEach(child => {
child.subcategories = traverse(data, child.id);
});
return children;
}