Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to add dynamic keys with nested level from the array in javascript

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);

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading