TehShrike / deepmerge

A library for deep (recursive) merging of Javascript objects
MIT License
2.75k stars 216 forks source link

Partial array merge #190

Open enrichman opened 4 years ago

enrichman commented 4 years ago

As far as I understood there is no way to handle a merge of a specific item in an array, is that correct?

I would like to update only the object in a specific index leaving the others untouched.

Should I handle this with a custom merge function?

macdja38 commented 4 years ago

Yup, a custom arrayMerge function would be able to do that. Alternatively if it's based on the object key you could try a custom customMerge that reads the key to determine if your custom array merge should be used.

enrichman commented 4 years ago

Thanks, the arrayMerge doesn't seems to fit well because is applied to all the arrays, but implementing a deeper logic to the customMerge seems to work.

I've tried something like this, but if you have some reviews to the snippet I would appreciate. I'm not skilled in js (especially with lambdas and such). 😄

const x = {
    foo: { bar: 3 },
    array: [
    {
        does: 'work',
        too: [ 1, 2, 3 ]
    },
    {
        does: 'yep',
        too: [ 1, 1, 1 ]
    }]
}

const y = {
    foo: { baz: 4 },
    quux: 5,
    array: {
         '__deepmerge_index': 0,
        does: 'replaced',
        too: [ 4, 5, 6 ]
    }
}

const deepmerge_index_key = '__deepmerge_index';

const mergeOnIndex = (obj1, obj2) => {
  if (Array.isArray(obj1) && typeof obj2 === 'object') {
    if (obj2.hasOwnProperty(deepmerge_index_key)) {
      var indexToChange = obj2[deepmerge_index_key];
      delete obj2[deepmerge_index_key];
      obj1[indexToChange] = obj2;
      return obj1;
    }
  }
  return merge(obj1, obj2)
}

const merged = merge(x, y, {
  customMerge: (key) => mergeOnIndex 
});

const output = {
    foo: {
        bar: 3,
        baz: 4
    },
    array: [
    {
        does: 'replaced',
        too: [ 4,5,6 ]
    },
    {
        does: 'yep',
        too: [ 1, 1, 1 ]
    }]
}