Search code examples
javascriptreactjsecmascript-6ecmascript-5

Updating the object based on the presence of the key else form a new object : Javascript


Have an object with following format:

let obj = {
  p2: {
    p21: [
      {
        key1: "val1",
        value1: "val2"
      },
      {
        prop: "test",
        value: "dummy"
      }
    ]
  }
}

I basically have to see if there is an object that has key "prop" and replace with whatever the passed value. If such key does not present create an object with { "prop" : "test" , value: passed_value} and add it to the p21 array. Also this object containing key "prop" can be present anywhere inside p21 array

Should be something like this

function checkAndUpdate(replacingValue) {
    if(obj's p21 has key name "prop")
    {
      //update its "value" to the passed "replacingValue"

    }
    else //if "prop" key not present
    {
       // create an object with { "prop": "test" , value: replacingValue} and add it to p21 array        
    }  
  }

Have tried following:

obj.p2.p21.map((elem) => {
    if(Object.keys(elem)[0] === "prop") 
        elem.value = updateValue;
})

Solution

  • Use .findIndex to find the index of the matching object. If it exists, .slice the array before and after it, and in the middle, insert the updated object. Otherwise, just spread the object into the array:

    let obj = {
      "p2": {
        "p21": [{
            "key1": "val1",
            "value1": "val2",
          },
          {
            "prop": "test",
            "value": "dummy"
          }
        ]
      }
    }
    
    function checkAndUpdate(value) {
      const newObj = { prop: 'test', value} 
      const arr = obj.p2.p21;
      const index = arr.findIndex(obj => obj.hasOwnProperty('prop'));
      const newArr = index !== -1
        ? [...arr.slice(0, index), newObj, ...arr.slice(index + 1)]
        : [...arr, newObj];
      const fullNewObj = {
        ...obj,
        p2: {
          ...obj.p2,
          p21: newArr
        }
      };
      return fullNewObj;
    }
    console.log(checkAndUpdate('foo'));

    To also check whether the value is undefined, and remove the matching object from the array if so, just make the appropriate if checks, and slice the array as needed:

    let obj = {
      "p2": {
        "p21": [{
            "key1": "val1",
            "value1": "val2",
          },
          {
            "prop": "test",
            "value": "dummy"
          }
        ]
      }
    }
    
    function checkAndUpdate(value) {
      const newObj = { prop: 'test', value} 
      const arr = obj.p2.p21;
      const index = arr.findIndex(obj => obj.hasOwnProperty('prop'));
      const newArr = (() => {
        if (index === -1) {
          if (value === undefined) {
            return arr;
          }
          return [...arr, newObj];
        }
        if (value === undefined) {
          return [...arr.slice(0, index), ...arr.slice(index + 1)];
        }
        return [...arr.slice(0, index), newObj, ...arr.slice(index + 1)];
      })();
      const fullNewObj = {
        ...obj,
        p2: {
          ...obj.p2,
          p21: newArr
        }
      };
      return fullNewObj;
    }
    console.log(checkAndUpdate('foo'));