I have a source array as below :
var source = [
{
node : 1,
text : "pen",
parent : null
},
{
node : 11,
text : "pencil",
parent : 1
},
{
node : 12,
text : "mango",
parent : 1
},
{
node : 111,
text : "mango",
parent : 11
},
{
node : 112,
text : "banana",
parent : 11
},
{
node : 211,
text : "Cilli",
parent : 12
},
{
node : 1111,
text : "banana",
parent : 111
},
{
node : 2,
text : "Grapes",
parent : null
},
{
node : 21,
text : "Mango",
parent : 2
},
{
node : 3,
text : "banana",
parent : null
},
]
So as you see the parent of node 1 is null, hence it is the parent node. Also, the parent of node 11 is 1, hence 11 is children of node 1 and so on. I want a target array created like below : I need to use below array to create a tree
var target = [
{
node : 1 ,
children :[
{
node : 11,
children : [
{
node : 111,
children :[
{
node:1111,
children :[]
}]
},
{
node : 112,
children:[]
}
]
},
{
node : 12,
children : []
},
]
},
{
node : 2,
children :[
{
node : 21,
children :[]
}]
},
{
node:3,
children:[]
}
]
I am trying array.forEach but that is not helping much
CodePudding user response:
This could work.
var source = [ { node : 1, text : "pen", parent : null }, { node : 11, text : "pencil", parent : 1 }, { node : 12, text : "mango", parent : 1 }, { node : 111, text : "mango", parent : 11 }, { node : 112, text : "banana", parent : 11 }, { node : 211, text : "Cilli", parent : 12 }, { node : 1111, text : "banana", parent : 111 }, { node : 2, text : "Grapes", parent : null }, { node : 21, text : "Mango", parent : 2 }, { node : 3, text : "banana", parent : null }, ];
const result = [];
const map = source.reduce((acc, {node, parent}) => {
acc[node] = {node, children: []};
return acc;
}, {});
source.forEach(({node, parent}) => {
if (!parent) {
result.push(map[node]);
} else {
map[parent]?.children?.push(map[node]);
}
});
console.log(result);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
// using an object `childrenFor` to keep track of all `.children` arrays while we fill them.
const target = source.reduce((childrenFor, item) => {
// adding the children array to item
item.children = childrenFor[item.node] ??= [];
// adding the item to the children array for its parent
(childrenFor[item.parent] ??= []).push(item);
//passing the cache through to the next iteration
return childrenFor;
}, {})[null]; // selecting the list for items with `parent: null`
field ??= []
does "get or create array".
var source = [{
node: 1,
text: "pen",
parent: null
},
{
node: 11,
text: "pencil",
parent: 1
},
{
node: 12,
text: "mango",
parent: 1
},
{
node: 111,
text: "mango",
parent: 11
},
{
node: 112,
text: "banana",
parent: 11
},
{
node: 211,
text: "Cilli",
parent: 12
},
{
node: 1111,
text: "banana",
parent: 111
},
{
node: 2,
text: "Grapes",
parent: null
},
{
node: 21,
text: "Mango",
parent: 2
},
{
node: 3,
text: "banana",
parent: null
},
];
const target = source.reduce((childrenFor, item) => {
item.children = childrenFor[item.node] ??= [];
(childrenFor[item.parent] ??= []).push(item);
return childrenFor;
}, {})[null];
console.log(target);
.as-console-wrapper{top:0;max-height:100%!important}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>