Search code examples
javascriptarraysobjectlodash

How Do I modify values in objects that is in a lodash grouped object?


I have a object created using Lodash's groupBy like this:

const GroupedData = {
  '01/02/2000': [{isChanged: true}, {isChanged: false}, {isChanged: false}],
  '02/02/2000': [{isChanged: true}, {isChanged: false}],
  '03/02/2000': [{isChanged: false}]
}

How do I change the isChanged boolean in all the objects to true? It is not a must to use lodash, but is there anyway to do it efficiently?


Solution

  • You could use _.mapValues() to map the values in your object. For each value (ie: array) in your object you can return a new array that is created by mapping (with _.map()), the current array value. You can use the map method to map each object to a new object with the isChanged property set to true, which you can do by merging a new object {isChanged: true} into the existing object with _.assign(). This approach will leave your original object as is, and return a new object with new array values/objects:

    const groupedData = {
      '01/02/2000': [{isChanged: true}, {isChanged: false}, {isChanged: false}],
      '02/02/2000': [{isChanged: true}, {isChanged: false}],
      '03/02/2000': [{isChanged: false}]
    };
    
    const res = _.mapValues(
      groupedData, 
      v => _.map(v, o => _.assign({}, o, {isChanged: true}))
    );
    console.log(res);
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

    The same result can be achieved with vanilla JS, using Object.entries() to map your values, and then using Object.fromEntries() to rebuild it once mapped:

    const groupedData = {
      '01/02/2000': [{isChanged: true}, {isChanged: false}, {isChanged: false}],
      '02/02/2000': [{isChanged: true}, {isChanged: false}],
      '03/02/2000': [{isChanged: false}]
    };
    
    const res = Object.fromEntries(Object.entries(groupedData).map(([key, val]) => [
      key, 
      val.map(obj => ({...obj, isChanged: true}))
    ]));
    console.log(res);


    If you're fine with modifying the object in place, you could just use a regular for..in loop to loop the keys of your object, which would be the most efficient, the lodash version of this is would be something like so:

    const groupedData = {
      '01/02/2000': [{isChanged: true}, {isChanged: false}, {isChanged: false}],
      '02/02/2000': [{isChanged: true}, {isChanged: false}],
      '03/02/2000': [{isChanged: false}]
    };
    
    _.forOwn(groupedData, arr => _.each(arr, obj => {
      obj.isChanged = true
    }));
    console.log(groupedData);
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>