How can I sort this array?
I am trying to group an array of objects from a parentId
that each element of the array brings, there can always be an indeterminate number of levels, the result I expect is the one I have in the output.
Input:
[
{
"_id": "123",
"name": "ABC",
"parentID": ""
},
{
"_id": "645",
"name": "ABC 2",
"parentID": "123"
},
{
"_id": "65",
"name": "ABC 3",
"parentID": ""
}
]
Output:
[
{
"_id": "123",
"name": "ABC",
"parentID": "",
"children": [
{
"_id": "645",
"name": "ABC 2",
"parentID": "123"
},
]
},
{
"_id": "65",
"name": "ABC 3",
"parentID": ""
}
]
Thanks for help
CodePudding user response:
This should work even for nested children:
const input = [{
"_id": "123",
"name": "ABC",
"parentID": ""
},
{
"_id": "645",
"name": "ABC 2",
"parentID": "123"
},
{
"_id": "65",
"name": "ABC 3",
"parentID": "645"
}
]
function map(data) {
const childMap = data.reduce((map, child) => {
return {
...map,
[child._id]: {
...child
}
};
}, {});
const root = [];
Object.values(childMap).forEach((child) => {
if (child.parentID) {
if (childMap[child.parentID]) {
const parent = childMap[child.parentID];
if (!parent.children) {
parent.children = [];
}
parent.children.push(child)
}
} else {
root.push(child);
}
})
return root;
}
console.log(map(input));
CodePudding user response:
You can try this approach with reduce
and filter
const input = [{
"_id": "123",
"name": "ABC",
"parentID": ""
},
{
"_id": "645",
"name": "ABC 2",
"parentID": "123"
},
{
"_id": "65",
"name": "ABC 3",
"parentID": ""
}
]
function mapChildren(data) {
//set the output with all results having no parent ids by default
let output = data.filter(x => !x.parentId)
//add children to existing results
output = data.reduce((result, current) => {
const {
parentID
} = current
if (!parentID) {
return result
}
const existingRecord = result.find(x => x._id === parentID)
if (existingRecord) {
if(!existingRecord.children) {
existingRecord.children = []
}
existingRecord.children.push({...current})
}
return result
}, output)
return output
}
console.log(mapChildren(input))
CodePudding user response:
Stuff like that is a job for database engines. You are not supposed to do this on Controller's side. The Model is supposed to send you data the way you want. Just ask the backend guy to make a route with the data sent like that, or just add some if
statements to your data parsing method to do stuff differently based on whether an object has parentId or not.
But if you really want to do it on frontend side, you can do it like this:
const data = [
{
_id: '123',
name: 'ABC',
parentID: '',
},
{
_id: '645',
name: 'ABC 2',
parentID: '123',
},
{
_id: '65',
name: 'ABC 3',
parentID: '',
},
];
const restructureData = (data) => {
const children = data.filter((object) => object.parentID);
const parents = data.filter((object) => !object.parentID);
for (let i = 0; i < children.length; i ) {
let parentIndex = parents
.map((object) => object._id)
.indexOf(children[i].parentID);
if (!parents[parentIndex].children) {
parents[parentIndex].children = [];
}
parents[parentIndex].children.push(children[i]);
}
return parents;
};
console.log(restructureData(data));
This will not work for nested children though.