javascriptarraysmergelodash

Deep Merge using Lodash


I have two arrays of objects that contain addresses that have a label and an object for the actual address:

var originalAddresses = [
  {
    label: 'home',
    address: { city: 'London', zipCode: '12345' }
  },
  {
    label: 'work',
    address: { city: 'New York', zipCode: '54321' }
  }
];

var updatedAddresses = [
  {
    label: 'home',
    address: { city: 'London (Central)', country: 'UK' }
  },
  {
    label: 'spain',
    address: { city: 'Madrid', zipCode: '55555' }
  }
];

Now I want to merge these arrays by label and compare the individual properties of the addresses and merge only the properties from the new address that are actually present. So the result should look like this:

var result = [
  {
    label: 'home',
    address: { city: 'London (Central)', zipCode: '12345', country: 'UK' }
  },
  {
    label: 'work',
    address: { city: 'New York', zipCode: '54321' }
  },
  {
    label: 'spain',
    address: { city: 'Madrid', zipCode: '55555' }
  }
]

How can I do this using lodash? I tried a combination of unionBy() and merge(). With unionBy() I was able to compare and join the arrays by label, but this always replaces the whole object. I can sure merge the addresses but this doesn't happen by label then.


Solution

  • You can turn both arrays into objects using _.keyBy(arr, 'label'), and then merge deep using _.merge():

    var originalAddresses = [{
      label: 'home',
      address: {
        city: 'London',
        zipCode: '12345'
      }
    }, {
      label: 'work',
      address: {
        city: 'New York',
        zipCode: '54321'
      }
    }];
    
    var updatedAddresses = [{
      label: 'home',
      address: {
        city: 'London (Central)',
        country: 'UK'
      }
    }, {
      label: 'spain',
      address: {
        city: 'Madrid',
        zipCode: '55555'
      }
    }];
    
    var result = _.values(_.merge(
      _.keyBy(originalAddresses, 'label'),
      _.keyBy(updatedAddresses, 'label')
    ));
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>