Merge two arrays and modify them in place (javascript)

Viewed 993

I have two arrays' of object, original and selected, sth like this:

original =[{ id: 4 , quantity: 4 },{ id: 2 , quantity: 2 },{ id: 76 , quantity: 2 }]
selected = [{ id: 2 , quantity: 1 }, { id: 100 , quantity: 7 }]

I want to be able to merge those arrays on id and if they got a similar id I should sum up the quantity,

The resulting array, in this case, should look something like this:

result=[{ id: 4 , quantity: 4 },{ id: 2 , quantity: 3 },{ id: 76 , quantity: 2 } , { id: 100 , quantity: 7 }]

I thought of doing something like this:

 const result =original.map(o => ({
            ...selectedArray.findIndex((s) => {(s.id === o.id) && selected)? return }
            ...original
         }));

But I am not sure how should I add to the quantity, any help or resources to look into would be appreciated.

3 Answers

You could find the object and update quantity or push a new object.

const 
    original = [{ id: 4, quantity: 4 }, { id: 2, quantity: 2 }, { id: 76, quantity: 2 }],
    selected = [{ id: 2, quantity: 1 }, { id: 100, quantity: 7 }],
    merged = [...original, ...selected].reduce((r, { id, quantity }) => {
        const item = r.find(q => q.id === id);
        if (item) item.quantity += quantity;
        else r.push({ id, quantity });
        return r;
    }, []);

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

A solution with a hash table.

const 
    mergeTo = (target, reference = {}) => ({ id, quantity }) => {
        if (reference[id]) reference[id].quantity += quantity;
        else target.push(reference[id] = { id, quantity });
    },
    original = [{ id: 4, quantity: 4 }, { id: 2, quantity: 2 }, { id: 76, quantity: 2 }],
    selected = [{ id: 2, quantity: 1 }, { id: 100, quantity: 7 }],
    merged = [],
    merge = mergeTo(merged);


original.forEach(merge);
selected.forEach(merge);

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Here is a simple to understand optimal solution that runs in O(n+m) time. You should use this if your array sizes are large. Where n and m are the lengths of array original and selected.

let original =[{ id: 4 , quantity: 4 },{ id: 2 , quantity: 2 },{ id: 76 , quantity: 2 }];
let selected = [{ id: 2 , quantity: 1 }, { id: 100 , quantity: 7 }];

let obj = Object.fromEntries(original.map(e => [e.id, e]));

selected.forEach(e => {
   if (obj[e.id]) {
       obj[e.id].quantity += e.quantity;
   } else {
       obj[e.id] = e;
   }
});

let result = Object.values(obj);

console.log(result);

I don't think this is not good method, but i think this will work.

 selected.forEach(obj => {
  var exists = original.find(x => x.id === obj.id);
  if(exists) {
    exists.quantity += obj.quantity;
  } else {
    original.push(obj);
  }
});

console.log(original);
Related