Search code examples
javascriptarraysmappingjavascript-objects

How can I create a merged object from an array of objects that preserves properties in the original object not changed from the new incoming object


I have to object/array sets...

var test = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var test2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];

Ultimately I want the objects from test2 to change properties in test but preserve the location property in the original object because it has not changed or even referenced in test2.

What I did was setup a mapping that key's the id and uses each object as the value.

The problem occurs that the value of the new object per the key will overwrite the previous original object in whole. Therefore, the location property gets wiped out from the original array.

notably from Object.assign() the bare object not presented as an array of objects will preserve integrity of the original object and only change underlying properties.

Here is an example of both:

array of objects:

var o1 = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var o2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // 0: {id: 1, prop: "casey"} 1: {id: 11, prop: "candle"} c: 3

singular object:

var o1 = {id: 1, prop: 'bill', location: 'san diego'};
var o2 = {id: 1, prop: 'casey'};
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // {id: 1, prop: "casey", location: "san diego", c: 3}

processing the object in a single format has the desired affect so perhaps the answer lies in that fact. Is there a concise way of doing this or will this need to be built out in a looped fashion processing one record at a time? If so, what would be an example of this?

Here is the mapping code I was working on:

var test = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var first = new Map();
for (const value of test) {
    //console.log(key + ' = ' + value.id);
    first.set(value.id, value);
    //console.log(first);
}
var test2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];
var second = new Map();
for (const value of test2) {
    second.set(value.id, value);
}

var merged = new Map([...first, ...second]);

let mergedArray = [];
for (var value of merged.values()) {
  console.log(' = ' + value);
    mergedArray.push(value);
}

console.log('merged', mergedArray);
// console.log(merged)

// console.log('second2', second);
// console.log('first2 ', first);

Solution

  • const merged = test.map(ele => {
      const found = test2.find(({id}) => id === ele.id) || {}
      return {...ele, ...found}
    })
    
    • loop over test
    • find the same id element in test2 (if not found set an empty object)
    • return the merged object where test is the source and test2 contains the overwrites/additions