I am working on an array of objects which has nested attributes, Is there any way to write a recursive function to achieve below output mentioned
const firstArray = [
{
groupId: '1',
childRows: [
{
groupId: '1a',
childRows: ['abc', 'def'],
},
{
groupId: '1b',
childRows: ['pqr', 'xyz'],
},
],
},
{
groupId: '2',
childRows: [
{
groupId: '2a',
childRows: ['abz', 'dxy'],
},
{
groupId: '2b',
childRows: ['egh', 'mno'],
},
],
},
];
How to write a function in es6 such that below output is returned
[
{ groupId: '1', childRows: ['abc', 'def', 'pqr', 'xyz'] },
{ groupId: '1a', childRows: ['abc', 'def'] },
{ groupId: '1b', childRows: ['pqr', 'xyz'] },
{ groupId: '2', childRows: ['abz', 'dxy', 'egh', 'mno'] },
{ groupId: '2a', childRows: ['abz', 'dxy'] },
{ groupId: '2b', childRows: ['egh', 'mno'] },
];
CodePudding user response:
I came up with this recursive function. The output objects are in the intended order.
const getNestedGroups = (array, groups = []) => {
const finalArray = [];
// Group list should be empty as it is filled here.
groups.length = 0;
array.forEach((group) => {
if (group.childRows.length > 0) {
// If the group does not have nested groups we just append it to the group list.
if (typeof group.childRows[0] === "string") {
groups.push(group);
}
// If the group has children, the same function is called for them.
else {
// Call function for child
const directChildren = [];
const childGroups = getNestedGroups(group.childRows, directChildren);
// Makes an object from the direct children (which were also made from their direct children if they had some).
let groupWithChildren = { groupId: group.groupId, childRows: [] };
childGroups.forEach((child) => {
groupWithChildren.childRows = groupWithChildren.childRows.concat(child.childRows);
});
// Adds child to group list.
groups.push(groupWithChildren);
groups = groups.concat(directChildren);
}
}
});
return finalArray.concat(groups);
}
You then call the function.
console.log(getNestedGroups(firstArray));
Here is the output.
[
{ groupId: '1', childRows: [ 'abc', 'def', 'pqr', 'xyz' ] },
{ groupId: '1a', childRows: [ 'abc', 'def' ] },
{ groupId: '1b', childRows: [ 'pqr', 'xyz' ] },
{ groupId: '2', childRows: [ 'abz', 'dxy', 'egh', 'mno' ] },
{ groupId: '2a', childRows: [ 'abz', 'dxy' ] },
{ groupId: '2b', childRows: [ 'egh', 'mno' ] }
]
CodePudding user response:
I found a solution. I tried to explain you with comments in the code
const firstArray = [
{
groupId: '1',
childRows: [
{groupId: '1a',childRows: ['abc', 'def']},
{groupId: '1b',childRows: ['pqr', 'xyz']}
]
},
{
groupId: '2',
childRows: [
{groupId: '2a',childRows: ['abz', 'dxy']},
{ groupId: '2b',childRows: ['egh', 'mno']}
]
},
];
function solution (arr){
const result = []
for (let i = 0; i < arr.length ; i ) {
let parent = [] // this is where I will accumulate all the "childRows" of the same parent
let oldResultLengt = result.length // remember this for now
for (let j = 0; j < arr[i].childRows.length; j ) {
const _childRows = arr[i].childRows[j].childRows // save the specific child array
result.push({'groupId':arr[i].childRows[j].groupId, 'childRows': _childRows}) // put the object into result array
parent.push(..._childRows) // add to parent array
}
/* in this part of the code, at the first iteration the let result looks this:
[
{"groupId": "1a", "childRows": ["abc", "def"]},
{"groupId": "1b", "childRows": ["pqr", "xyz"]}
]
but oldResultLength is still 0, so I use splice to insert the parent element before their own childrens
*/
result.splice(oldResultLengt, 0, {'groupId' : arr[i].groupId, 'childRows': parent})
}
return result
}
console.log(solution(firstArray))
Function without comments:
function solution (arr){
const result = []
for (let i = 0; i < arr.length ; i ) {
let parent = []
let oldResultLengt = result.length
for (let j = 0; j < arr[i].childRows.length; j ) {
const _childRows = arr[i].childRows[j].childRows
result.push({'groupId':arr[i].childRows[j].groupId, 'childRows': _childRows})
parent.push(..._childRows)
}
result.splice(oldResultLengt, 0, {'groupId' : arr[i].groupId, 'childRows': parent})
}
return result
}