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]
.