Hello, Hope you're doing well & solving interesting problems using your programming skills.🔥
In this blog, we will try to solve one such interesting problem related to flattening the object which is asked in javascript interviews.
I have breakdown the whole tutorial into 4 sections -
- Input
- Output
- Approach (logic)
- Assemble (put everything together)
Let's start!🚀
Input
This is our unflatten object containing data of an user.
const user = {
name: 'John',
address: {
personal: {
street: 'Victor Plains',
city: 'Wisokyburgh',
},
office: {
city: 'South Elvis',
area: {
landmark: 'Hoeger Mall',
},
},
},
};
Output
We need to flat the object like this -
{
user_name: "John",
user_address_personal_street: "Victor Plains",
user_address_personal_city: "Wisokyburgh",
user_address_office_city: "South Elvis",
user_address_office_area_landmark: "Hoeger Mall"
}
Approach
If you closely look at our input object, you'll see a pattern of nested objects.
const OBJECT = {
name: 'John',
OBJECT: {
OBJECT: {
street: 'Victor Plains',
city: 'Wisokyburgh',
},
OBJECT: {
city: 'South Elvis',
OBJECT: {
landmark: 'Hoeger Mall',
},
},
},
};
So we need to iterate over the nested objects & flat them one by one.
But if we want to flat each object at a time, we need to breakdown the nested objects into a single object recursively.
Recursively? 🤔
Yes, We will use recursion to solve this problem.
What is Recursion?
Recursion is a phenomenon used to solve complex problems by breaking them down into simpler ones.
Recursive Function
When we apply this phenomenon in a function, that function will call itself again and again until we reach at the breaking condition.
*Let's define our recursive function - *
const recursiveFunc = (obj, parentKey, flattenObj) => {
// we will write our logic here.
};
- obj: our input object
- parentKey: To keep a track of parent object because we need to append parent keys while iterating over the input obj -
user_address_office_area_landmark: "Hoeger Mall"
- flattenObj: an empty object to store flatten obj on each iteration.
While looping through unflatten object, we will only flat those key whose type is object.
So, we need a function which takes key
as item & return true
if the key is an object.
const isAnObject = (item) => {
return (
item !== null &&
typeof item === 'object' &&
Object.prototype.toString.call(item) === '[object Object]'
);
};
Now we need to loop through the input object ( unflatten ) & store the flatten key-value pair inside flattenObj
for (let key in obj) { // 1
let finalKey = `${parentKey}_${key}`; // 2
if (isAnObject(obj[key])) { // 3
recursiveFunc(obj[key], finalKey, flattenObj); // 4
} else {
flattenObj[finalKey] = obj[key]; // 5
}
}
Let's understand it line by line.
// 1 - let key in obj
this line will give key of the key-value pair on each iteration. name
, address
, personal
& so on.
// 2 - we are adding the parent key before current key to make it look like this at the end - user_address_personal_street: "Victor Plains"
. When we iterate over address obj, the user will be the parent. so we add the user before address - user_address
& store it in finalKey
.
// 3 - we are checking if the current key is an object or not using isAnObject
function which we've already defined.
// 4 - If the key is an object, we will call recursiveFunc
again with the updated value of obj
, parentKey
& flattenObj
.
// 5 - If the key is not object, we will store the finalKey
(user_address_personal_street) as key & key
("Victor Plains") as value inside flattenObj.
Let's pass our initial data & console the output.
let flattenObj = {};
recursiveFunc(user, 'user', flattenObj);
console.log(flattenObj);
So when we invoke the recursiveFunc, it'll run the loop & iterate over user
object.
Initial value -
- obj: user
- parentKey: 'user'
- flattenObj: {}
First Iteration
Now key
is name
- finalKey = 'user_name'
-
name
is not an object Result
flattenObj = { user_name: "John" }
Second Iteration
Now key
is address
- finalKey = 'user_address'
-
address
is an object
Result
call recursiveFunc again with new values -
- obj: address
- parentKey: "user_address"
flattenObj: { user_name: "John" }
Third Iteration
Now key
is personal
- finalKey = 'user_address_personal'
-
personal
is an object
Result
call recursiveFunc again with new values -
- obj: personal
- parentKey: "user_address_personal"
flattenObj: { user_name: "John" }
Fourth Iteration
Now key
is street
- finalKey = 'user_address_personal_street'
-
street
is not an object
Result
flattenObj = {
user_name: "John",
user_address_personal_street: "Victor Plains"
}
...and iterations will go on until it reach the last key.
The final output will be - 🎉
flattenObj = {
user_name: "John",
user_address_personal_street: "Victor Plains",
user_address_personal_city: "Wisokyburgh",
user_address_office_city: "South Elvis",
user_address_office_area_landmark: "Hoeger Mall"
}
Assemble
Here's the whole code for flattening an object.
const user = {
name: 'John',
address: {
personal: {
street: 'Victor Plains',
city: 'Wisokyburgh',
},
office: {
city: 'South Elvis',
area: {
landmark: 'Hoeger Mall',
},
},
},
};
const recursiveFunc = (obj, parentKey, flattenObj) => {
const isAnObject = (item) => {
return (
item !== null &&
typeof item === 'object' &&
Object.prototype.toString.call(item) === '[object Object]'
);
};
for (let key in obj) {
let finalKey = `${parentKey}_${key}`;
if (isAnObject(obj[key])) {
recursiveFunc(obj[key], finalKey, flattenObj);
} else {
flattenObj[finalKey] = obj[key];
}
}
};
let flattenObj = {};
recursiveFunc(user, 'user', flattenObj);
console.log(flattenObj);
Conclusion
Hope after reading this blog, you've understood -
- How to approach a problem.
- How to flatten an object using recursion.
If you find this blog as helpful, don't forget to share it.
And incase you know any other ways to flatten an object in javaScript, please share it in the comments.
Top comments (0)