I have the following JavaScript object:
this is basically a list of comments, the actual list is much longer and more deeply nested, so this is a simplified version.
[
{
id: 200,
comment: "If you have any question, please comment here.",
depth: 1,
parent_id: null,
comments: [],
},
{
id: 201,
comment: "Hi, I'm stuck at the installation of node.js. Can I ask help?",
depth: 2,
parent_id: 200,
comments: [],
},
{
id: 202,
comment: "This is a detailed explanation, great.",
depth: 1,
parent_id: null,
comments: [],
},
{
id: 203,
comment: "Hello! That's weird. Do you have a screenshot?",
depth: 3,
parent_id: 201,
comments: [],
},
]
I want to convert the above to the following. But I think I use .map or similar, but I don't have a clear idea of how to implement this.
[
{
id: 200,
comment: "If you have any question, please comment here.",
depth: 1,
parent_id: null,
comments: [
{
id: 201,
comment: "Hi, I'm stuck at the installation of node.js. Can I ask help?",
depth: 2,
parent_id: 200,
comments: [
{
id: 203,
comment: "Hello! That's weird. Do you have a screenshot?",
depth: 3,
parent_id: 201,
comments: [],
},
],
},
],
},
{
id: 202,
comment: "This is a detailed explanation, great.",
depth: 1,
parent_id: null,
comments: [],
},
]
Thanks.
a solution with array.reduce
var data = [
{
id: 200,
comment: "If you have any question, please comment here.",
depth: 1,
parent_id: null,
comments: [],
},
{
id: 201,
comment: "Hi, I'm stuck at the installation of node.js. Can I ask help?",
depth: 2,
parent_id: 200,
comments: [],
},
{
id: 202,
comment: "This is a detailed explanation, great.",
depth: 1,
parent_id: null,
comments: [],
},
{
id: 203,
comment: "Hello! That's weird. Do you have a screenshot?",
depth: 3,
parent_id: 201,
comments: [],
},
];
const result = data.reduce((acc, curr) => {
let parent = (curr.parent_id) ? data.filter(el => el.id === curr.parent_id) : [];
if (parent.length) {
parent[0].comments.push(curr);
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(result);
One approach to seem to work is by using a double loop with forEach() and a conditional statement to push the elements inside the comments array if conditions are met.
let data = [
{
id: 200,
comment: "If you have any question, please comment here.",
depth: 1,
parent_id: null,
comments: [],
},
{
id: 201,
comment: "Hi, I'm stuck at the installation of node.js. Can I ask help?",
depth: 2,
parent_id: 200,
comments: [],
},
{
id: 202,
comment: "This is a detailed explanation, great.",
depth: 1,
parent_id: null,
comments: [],
},
{
id: 203,
comment: "Hello! That's weird. Do you have a screenshot?",
depth: 3,
parent_id: 201,
comments: [],
},
]
data.forEach((el_one) => {
data.forEach((el_two) => {
if(el_one.parent_id === el_two.id){
el_two.comments.push(el_one)
}
})
})
console.log(data)
Create a plain object with elements, walk through your array and place all children elements into the comments field accessing corresponding parent element via that plain object. Then filter out all non-root elements (i assume your data is stored in the array named data):
// Fill in id-accessed storage
var elements_by_id = {};
data.forEach((el) => elements_by_id[el.id] = el );
// Feed comments
data.forEach((el) => el.parent_id ? ( elements_by_id[el.parent_id].comments.push(el) ) : '' );
// Remove non-root elements
data = data.filter( (el) => !el.parent_id );