Hi I want to create new object on the basis of path array. It will be dynamic. I tried with reduce but it is not giving correct result.
const obj = {
"e": [{
"name": "moviename",
"path": ["a"]
},
{
"name": "hero",
"path": ["a", "b"]
},
{
"name": "desc",
"path": ["c"]
},
{
"name": "udf",
"path": []
}
]
}
// this is what i want this object to be created programatically. after parsing above obj.
const output = {
"a": {
"moviename": "",
"b": {
"hero": ""
}
},
"c" : {
"desc": ""
},
"udf": ""
}
const payload = {};
obj.e.forEach((item) => {
if (item.path.length === 0) {
payload = {
payload,
[item.name]: ''
};
} else {
item.path.reduce((o, s, index) => {
if ((index + 1) === item.path.length) {
return o[s] = {
[item.name]: ''
};
}
return o[s] = {};
}, payload);
}
});
console.log(payload);
Advertisement
Answer
You can use simple for
loops — reduce
would also work (see further down), but I think the overhead of a callback is not worth it:
function convert(arr) {
const output = {};
for (const {name, path} of arr) {
let node = output;
for (let prop of path) {
node = (node[prop] ??= {});
}
node[name] = "";
}
return output;
}
const obj = {"e": [{"name": "moviename","path": ["a"]},{"name": "hero","path": ["a", "b"]},{"name": "desc","path": ["c"]},{"name": "udf","path": []}]};
console.log(convert(obj.e));
With reduce
:
Using reduce
it would translate to this:
function convert(arr) {
return arr.reduce((output, {name, path}) => {
let node = output;
for (let prop of path) {
node = (node[prop] ??= {});
}
node[name] = "";
return output;
}, {});
}
const obj = {"e": [{"name": "moviename","path": ["a"]},{"name": "hero","path": ["a", "b"]},{"name": "desc","path": ["c"]},{"name": "udf","path": []}]};
console.log(convert(obj.e));
With double reduce
:
If the inner loop is also done through reduce
, then:
function convert(arr) {
return arr.reduce((output, {name, path}) => {
path.reduce((node, prop) => node[prop] ??= {}, output)[name] = "";
return output;
}, {});
}
const obj = {"e": [{"name": "moviename","path": ["a"]},{"name": "hero","path": ["a", "b"]},{"name": "desc","path": ["c"]},{"name": "udf","path": []}]};
console.log(convert(obj.e));
The logical nullish assignment operator
If your environment has no support for ??=
then use one of the following alternatives:
node[prop] ||= {}
(node[prop] = node[prop] ?? {})
(node[prop] = node[prop] || {})
Some comments on your code
As this function builds the object from scratch, it is not really necessary to treat intermediate versions of the object as immutable — as your code attempts to do at least in the case of path.length == 0
: just keep extending the object through mutation.
return o[s] = {};
is destructive: if the property was already created from a previously processed path, then this will overwrite whatever was already assigned to o[s]
.