Search code examples
javascriptlodash

How to merge two objects and make sure when there's duplicated keys, take one of the objects' values first?


I have two objects created with Lodash's groupBy like this:

const prevGroupedData = {
  '01/04/2000': [{data: 1}, {data: 2}, {data: 3}],
  '02/04/2000': [{data: 1}, {data: 2}]
}

const GroupedData = {
  '02/04/2000': [{data: 3}, {data: 4}],
  '03/04/2000': [{data: 1}]
}

So when I merge these two objects, I wanna make sure that it is the prevGroupedData that is merged first, that means something like:

const result = {
  '01/04/2000': [{data: 1}, {data: 2}, {data: 3}],
  '02/04/2000': [{data: 1}, {data: 2}, {data: 3}, {data: 4}], 
  '03/04/2000': [{data: 1}]
}

But not:

const result = {
  '01/04/2000': [{data: 1}, {data: 2}, {data: 3}],
  '02/04/2000': [{data: 3}, {data: 4}, {data: 1}, {data: 2}], 
  '03/04/2000': [{data: 1}]
}

I have tried something like lodash's merge but it gives the second result:

let result = _.merge(prevGroupedData, GroupedData);
//gives second result

So how do I make sure that it is the prevGroupedData that has higher priority when there's duplicated keys?


Solution

  • this is possible with mergeWith. The docs have a similar looking example

    const prevGroupedData = {
      '01/04/2000': [{data: 1}, {data: 2}, {data: 3}],
      '02/04/2000': [{data: 1}, {data: 2}]
    }
    
    const GroupedData = {
      '02/04/2000': [{data: 3}, {data: 4}],
      '03/04/2000': [{data: 1}]
    }
    ;
    
    const customizer = (objValue, srcValue) => {
      if (_.isArray(objValue)) {
        return objValue.concat(srcValue)
      }
    }
      
    const res = _.mergeWith(prevGroupedData, GroupedData, customizer)
    console.log(res)
    console.log(prevGroupedData)
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

    Note that the above has mutated the prevGroupedData. If you don't need that to happen you can assign an empty {} as the destination.

    const prevGroupedData = {
      '01/04/2000': [{data: 1}, {data: 2}, {data: 3}],
      '02/04/2000': [{data: 1}, {data: 2}]
    }
    
    const GroupedData = {
      '02/04/2000': [{data: 3}, {data: 4}],
      '03/04/2000': [{data: 1}]
    }
    ;
    
    const customizer = (objValue, srcValue) => {
      if (_.isArray(objValue)) {
        return objValue.concat(srcValue);
      }
    }
     
    // prevGroupedData not mutated, destination object is {} now
    const res = _.mergeWith({},prevGroupedData, GroupedData, customizer)
    console.log(res)
    console.log(prevGroupedData)
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>