Reputation: 343
How can I change all nested object values to "true" without using extra space Can anyone help me in this. I have tried in this way but I am not getting the logic to handle the nested object
P.S: Please don't concentrate about "true" or "false" is in string because it is mock data,I just want logic to implement which I am failing to do.
const config = {
header:{"logo":"true","nav":"false","user":"false"},
searchResults:{"listView":"false","favorite":"true","share":"false","pagination":"true","filters":"true","sortBy":"false"},
sharedLinks:{},
learnerLinks:{},
lukePreview:{"toc":"false","controls":"false"},
lukeLaunch:{"toc":"false","controls":"false"},
misc:{"import":"true"}
}
function changeBoolean(obj,propName){
for(let i in obj){
if( typeof obj[i] === 'object'){
changeBoolean(obj[i],i)
}
}
return obj
}
console.log(changeBoolean(config,'header'))
Upvotes: 3
Views: 1015
Reputation: 19070
You can do:
const config = {
header: { "logo": "true", "nav": "false", "user": "false" },
searchResults: { "listView": "false", "favorite": "true", "share": "false", "pagination": "true", "filters": "true", "sortBy": "false" },
sharedLinks: {},
learnerLinks: {},
lukePreview: { "toc": "false", "controls": "false" },
lukeLaunch: { "toc": "false", "controls": "false" },
misc: { "import": "true" }
}
const changeBoolean = o => Object.entries(o).reduce((a, [k, v]) => {
a[k] = typeof v === 'object' ? changeBoolean(v) : 'true'
return a
}, {})
const newConfig = changeBoolean(config)
console.log(newConfig)
Upvotes: 0
Reputation: 350310
You write:
Can we modify nested object values without modifying original object?
This sounds like a contradiction. When you mutate a nested object, then that is a mutation of the original object. It looks like you want immutability. This means that as soon as you need a change in a nested object, you create a copy of it that has the change, and this change will then bubble upwards, resulting in new copies of objects as they receive a new "child" object.
...without extra space
You cannot have both: either you mutate the original object (in its nested parts), or you create a new one. If you don't want the original object to mutate, then you obviously need space for the replacing object.
Your input object has no boolean values. It has strings like "false" and "true", but those are not booleans. So I suggest to work with truly boolean values, without the quotes
Your code is not setting any property, so it can never mutate anything to your object
Your data has no "header" property, so that would be another reason why your code could not have changed anything.
The second argument you pass to the recursive call is i
, which is not the property you wanted to change. You should just pass propName
there.
false
it should become true
and vice versa.Here is how I would do that. This snippet runs with 2 test cases: one that doesn't change anything, and another that does:
function changeBoolean(obj, propName) {
if (Object(obj) !== obj) return obj; // A primitive value: nothing changes
let changed = false;
let pairs = Object.entries(obj).map(function ([key, value]) {
let changedValue = key === propName && typeof value === "boolean" ? !value
: changeBoolean(value, propName);
changed ||= changedValue !== value;
return [key, changedValue];
});
return changed ? Object.fromEntries(pairs) : obj;
}
const config = {
header:{logo: true, nav: false, user: false},
searchResults:{listView: false, favorite: true, share: false, pagination: true, filters: true, sortBy: false},
sharedLinks:{},
learnerLinks:{},
lukePreview:{toc: false, controls: false},
lukeLaunch:{toc: false, controls: false},
misc:{import: true}
};
// Test 1
let header = changeBoolean(config, 'header');
console.log("header:", header === config ? "no change" : header);
// Test 2
let toc = changeBoolean(config, 'toc');
console.log("toc:", toc === config ? "no change" : toc);
Upvotes: 0
Reputation: 322
Try to assign the function's result, like this:
function changeBoolean(obj, propName) {
for (let i in obj) {
if (typeof obj[i] === "object") {
obj[i] = changeBoolean(obj[i], propName);
} else {
obj[i] = "true";
}
}
return obj;
}
Upvotes: 2