Search code examples
javascriptarraysarray-merge

Merge two object arrays by adding object values by same id while also adding unique id


I have a working function which merges two objects arrays with different lengths (source > target under three conditions :

  1. include objects with unique id from target array
  2. include objects with unique id from source array
  3. include objects with duplicate ids by subtracting the target value from source value

My question is, how can I change this code to be leaner and efficiently? By just looking at the code it seems like it would take a lot of computational resources..

I tried to concat the arrays and run them through a while loop but could not figure out a way to differentiate which object belonged to which array..

let target = [
  { id:1, x: 50 },
  { id:2, x: 30 },
  { id:3, x: 30 }
];

let source = [
  { id:1, x: 30 },
  { id:2, x: 13 },
  { id:4, x: 100 },
  { id:5, x: 5 }
];

let arrayResult = [];
function compute( target, source ) {
    for (let i = 0; i < source.length; i++ ) {
        let srcObj = source[i];
        let tarObj = target.find(d => d.id === srcObj.id)

        if (tarObj) {
            let result = {
                id: srcObj.id,
                x: srcObj.x - tarObj.x
            }
            arrayResult.push(result);
        } else {
            arrayResult.push(srcObj);
        }
    }
    for( let i = 0; i < target.length; i ++ ) {
        let src = target[i];
        let tar = arrayResult.find(d => d.id === src.id);
        if (!tar){
            arrayResult.push(src)
        }
    }
}
compute(target, source);
console.log(arrayResult);


Solution

  • You can make this more efficient by generating an array mapping id values in source to their index in the array. Then you can iterate over target, checking whether each objects id value has an entry in the srcids array, and if so, updating the corresponding source x value, otherwise pushing the object into the source array:

    let target = [
      { id:1, x: 50 },
      { id:2, x: 30 },
      { id:3, x: 30 }
    ];
    
    let source = [
      { id:1, x: 30 },
      { id:2, x: 13 },
      { id:4, x: 100 },
      { id:5, x: 5 }
    ];
    
    const srcids = source.reduce((c, o, i) => {
      c[o.id] = i;
      return c;
    }, []);
    
    target.forEach(o => {
      if (srcids[o.id] !== undefined) {
        source[srcids[o.id]].x -= o.x;
      } else {
        source.push(o);
      }
    });
    
    console.log(source);