Hi i want to get children tree from a category list.
here is my input data
[
{ "parent_id": -1, "name": "Toothpaste", "id": 99 },
{
"parent_id": -1,
"name": "Cake",
"id": 3
},
{
"parent_id": 3,
"name": "Chocolate Cake",
"id": 4
},
{
"parent_id": 3,
"name": "Walnut Cake",
"id": 5
},
{
"parent_id": 4,
"name": "Chocolate Cake mixin 1",
"id": 6
}
]
my desired output will look like below one
[ { "parent_id": -1, "name": "Toothpaste", "id": 99 },
{
"parent_id": -1,
"name": "Cake",
"id": 3,
"children":[
{
"parent_id": 3,
"name": "Chocolate Cake",
"id": 4,
"children":[ //<--- observe this one not there in my output
{
"parent_id": 4,
"name": "Chocolate Cake mixin 1",
"id": 6
}
]
},
{
"parent_id": 3,
"name": "Walnut Cake",
"id": 5
}
],
}
]
The problem i'm facing is that i'm unable to push data into 2nd level i,e chocolate cake is having children but i'm unable to push that into chocolate cake children
Note: solution must work for any level of nesting
here is what i have tried
function getChildrenTree(childList){
let childMap = {};
for(let i = 0; i < childList.length; i ){
if(childList[i].parent_id === -1)
childMap[childList[i].id] = {name:childList[i].name,children:[]};
}
for(let i = 0; i < childList.length; i ){
if(childMap && childMap.hasOwnProperty(childList[i].parent_id) && childMap[childList[i].parent_id].hasOwnProperty('children')) childMap[childList[i].parent_id].children.push(childList[i]);
}
return Object.values(childMap);
}
getChildrenTree([ { "parent_id": -1, "name": "Toothpaste", "id": 99 },{ "parent_id": -1, "name": "Cake", "id": 3 }, { "parent_id": 3, "name": "Chocolate Cake", "id": 4 }, { "parent_id": 3, "name": "Walnut Cake", "id": 5 }, { "parent_id": 4, "name": "Chocolate Cake mixin 1", "id": 6 } ])
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Here's an approach you can try.
const flat = [
{ "parent_id": -1, "name": "Toothpaste", "id": 99 },
{
"parent_id": -1,
"name": "Cake",
"id": 3
},
{
"parent_id": 3,
"name": "Chocolate Cake",
"id": 4
},
{
"parent_id": 3,
"name": "Walnut Cake",
"id": 5
},
{
"parent_id": 4,
"name": "Chocolate Cake mixin 1",
"id": 6
}
];
const makeTree = (arr, parent) => {
const branch = arr.filter(node => node.parent_id === parent);
branch.forEach(node => {
const children = makeTree(arr, node.id);
if (children.length) {
node.children = children;
}
});
return branch;
};
const tree = makeTree(flat, -1);
console.log(tree);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You could take a single loop and and object for collecting the nodes and return a tree by taking all children from the root node.
const
buildTree = (data, root) => {
var t = {};
data.forEach(o => {
Object.assign(t[o.id] = t[o.id] || {}, { ...o });
((t[o.parent_id] ??= {}).children ??= []).push(t[o.id]);
});
return t[root].children
},
data = [{ parent_id: -1, name: "Toothpaste", id: 99 }, { parent_id: -1, name: "Cake", id: 3 }, { parent_id: 3, name: "Chocolate Cake", id: 4 }, { parent_id: 3, name: "Walnut Cake", id: 5 }, { parent_id: 4, name: "Chocolate Cake mixin 1", id: 6 }],
tree = buildTree(data, -1);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>