DEV Community

Cover image for Flatten Deeply Nested Objects
Chukwuma Anyadike
Chukwuma Anyadike

Posted on

Flatten Deeply Nested Objects

Here is a way to flatten a deeply nested object using loops and various array methods. This is a response to Daily JavaScript Challenge #JS-31: Flatten Nested Objects.

Principles used:

Looping through an object:

For..in syntax is used to loop through key-value pairs in a POJO (plain old JavaScript object). Recall that for..of syntax is used to loop through array elements.

Recursion:

The flatten function is invoked within the function itself, hence recursively, to flatten any deeply nested object whether as a key value or as an array element.

Type identification using typeof operator:

In this method the typeof operator is used to identify nested objects.

Array methods:

The array methods map() and some() are used. The former is familiar to most, but the latter requires explanation. The method some() takes a callback function returning a boolean value as an argument. If any (SOME) of the elements in the array meet the condition then the return value is true. There is also an every() method which is similar to some syntactically but returns true only if EVERY element meets the condition.

function flatten(obj) {
    let flattenedObj = {};  //initial empty object to place new key value pairs

    //loop through key value pairs
    for (const key in obj) {
        //if key points to an object which is not an array (recall arrays ARE objects), then recursively flatten that object
        if (typeof obj[key] == "object" && !Array.isArray(obj[key])) {
            const tempObj = flatten(obj[key]);
            for (const tempKey in tempObj) {
                flattenedObj[`${key}.${tempKey}`] = tempObj[tempKey];
            }
            //if key points to an array then recursively flatten any objects present in the array
        } else if (Array.isArray(obj[key])) {
            if (obj[key].some(e => typeof e === "object"))
                flattenedObj[key] = obj[key].map((element) => typeof element === "object" ? flatten(element) : element);
            else flattenedObj[key] = obj[key];
        } else {
            flattenedObj[key] = obj[key];
        }
    }

    return flattenedObj;
}
Enter fullscreen mode Exit fullscreen mode

Here are some sample objects to use. One is a deeply nested object. The other is also a deeply nested object with arrays containing differing types. The above method works for both. Give this a try. Enjoy.

const obj = {
    firstName: "Heath",
    lastName: "Frederick",
    occupation: {
        name: "Software Engineer",
        duties: ["automation testing", "bug fixes", "deployments"],
        workAddress: {
            street: "Las Colinas Ave",
            city: "Irving",
            state: "Texas"
        }
    }
}

const arrOfObj = [
    {
        label: "first",
        id: 1,
        children: []
    },
    {
        label: "second",
        id: 2,
        children: [
            {
                label: "third",
                id: 3,
                children: [
                    {
                        label: "fifth",
                        id: 5,
                        children: []
                    },
                    {
                        label: "sixth",
                        id: 6,
                        children: [
                            {
                                label: "seventh",
                                id: 7,
                                children: []
                            }
                        ]
                    }
                ]
            },
            {
                label: "fourth",
                id: 4,
                children: []
            },
            1,
            "different Type",
            true
        ]
    }
];
Enter fullscreen mode Exit fullscreen mode

Top comments (0)