Search code examples
javascriptarraysobjectrecursion

How to create or convert from input to output optimized way?


I'm trying to create path in array of object based on parent child relationship using below code and getting maximum call stack size exceeded error

var input = [{
        clientArrngmntId: 12,
        level: 1,
        hasChild: true,
        parentId: 0,
        idx: 0,
    },
    {
        clientArrngmntId: 13,
        level: 2,
        hasChild: true,
        parentId: 12,
        idx: 2,
    },
    {
        clientArrngmntId: 14,
        level: 3,
        hasChild: false,
        parentId: 13,
        idx: 3,
    },
    {
        clientArrngmntId: 15,
        level: 2,
        hasChild: false,
        parentId: 12,
        idx: 4,
    },
    {
        clientArrngmntId: 16,
        level: 1,
        hasChild: false,
        parentId: 0,
        idx: 5,
    }]
    
    var output = [{
        clientArrngmntId: 12,
        level: 1,
        hasChild: true,
        parentId: 0,
        path:[12],
        idx: 0,
    },
    {
        clientArrngmntId: 13,
        level: 2,
        hasChild: true,
        parentId: 12,
        path: [12,13],
        idx: 2,
    },
    {
        clientArrngmntId: 14,
        level: 3,
        hasChild: false,
        parentId: 13,
        path: [12,13,14],
        idx: 3,
    },
    {
        clientArrngmntId: 15,
        level: 2,
        hasChild: false,
        parentId: 12,
        path: [12,15],
        idx: 4,
    },
    {
        clientArrngmntId: 16,
        level: 1,
        hasChild: false,
        parentId: 0,
        path: [16]
        idx: 5,
    }]


const processDataAlt = data => {
    const flattenedData = []
    const flattenRowRecursive = (row, parentPath) => {
        const dataPath = [ ...parentPath, row.clientArrngmntId ]
        flattenedData.push({
            ...row,
            dataPath,
        })
        if (row.hasChild && !flattenedData.includes(row.clientArrngmntId)) {
            flattenRowRecursive(row, dataPath)
        }
    }
    data.forEach(row => flattenRowRecursive(row, []))
    return flattenedData
}

Solution

  • To create a path in an array of objects based on the parent-child relationship without causing a call stack size exceeded error, you can use an iterative approach rather than a recursive one.

    Here's an example of how you can achieve this using a loop to build the path for each object in the input array:

    var input = [{
    clientArrngmntId: 12,
    level: 1,
    hasChild: true,
    parentId: 0,
    idx: 0,
    },
    {
    clientArrngmntId: 13,
    level: 2,
    hasChild: true,
    parentId: 12,
    idx: 2,
    },
    {
    clientArrngmntId: 14,
    level: 3,
    hasChild: false,
    parentId: 13,
    idx: 3,
    },
    {
    clientArrngmntId: 15,
    level: 2,
    hasChild: false,
    parentId: 12,
    idx: 4,
    },
    {
    clientArrngmntId: 16,
    level: 1,
    hasChild: false,
    parentId: 0,
    idx: 5,
    }];
    
    // Create a map to store the paths based on clientArrngmntId
    const pathMap = [];
    
    // Iterate over each object in the input array
    input.forEach(obj => {
    const path = [obj.clientArrngmntId]; // Initialize the path with the current clientArrngmntId
    let parentId = obj.parentId;
    
    // Traverse the parent hierarchy to build the complete path
    while (parentId !== 0) {
        const parentObj = input.find(parent => parent.clientArrngmntId === parentId);
        path.unshift(parentObj.clientArrngmntId);
        parentId = parentObj.parentId;
    }
    
    // pathMap[obj.clientArrngmntId] = path; // Store the path in the map
    pathMap.push(Object.assign(obj, {path: path}))
    
    });
    
    console.log(pathMap); // Output the paths for each object