deepmerge icon indicating copy to clipboard operation
deepmerge copied to clipboard

Partial array merge

Open enrichman opened this issue 4 years ago • 2 comments

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?

enrichman avatar Feb 26 '20 19:02 enrichman

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.

macdja38 avatar Feb 26 '20 19:02 macdja38

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 ]
	}]
}

enrichman avatar Feb 26 '20 20:02 enrichman