Skip to content Skip to sidebar Skip to footer

Javascript: Merge Two Arrays Of Objects, Only If Not Duplicate (based On Specified Object Key)

Background Say I have an initial array of objects: var initialData = [ { 'ID': 1, 'FirstName': 'Sally' }, { 'ID': 2, 'FirstName': 'Jim'

Solution 1:

You can create a set of IDs from initialData and this will make "check if ID is already in initial data" faster - O(1):

var initialData = [{
    'ID': 1,
    'FirstName': 'Sally'
  },
  {
    'ID': 2,
    'FirstName': 'Jim'
  },
  {
    'ID': 3,
    'FirstName': 'Bob'
  }
];

var newData = [{
    'ID': 2,
    'FirstName': 'Jim'
  },
  {
    'ID': 4,
    'FirstName': 'Tom'
  },
  {
    'ID': 5,
    'FirstName': 'George'
  }
];

var ids = newSet(initialData.map(d => d.ID));
var merged = [...initialData, ...newData.filter(d => !ids.has(d.ID))];

console.log(merged);

The final runtime of this approach is O(n + m).

If you want to be slightly more efficient, you can consider looping through newData and pushing any new elements to the final result array manually (instead of using filter and the spread operator).

Solution 2:

Actually, if you are interested on performance, you could think on changing your initialData structure to something like this:

var initialData = {
    "1": {'FirstName': 'Sally'},
    "2": {'FirstName': 'Jim'},
    "3": {'FirstName': 'Bob'}
};

In other words, we use the IDs as the keys of an object, this will give you O(1) on access the data, and O(1) in the exists test. You can get this structure using the next approach with reduce():

var initialData = [
    {'ID': 1, 'FirstName': 'Sally'},
    {'ID': 2, 'FirstName': 'Jim'},
    {'ID': 3, 'FirstName': 'Bob'}
];

let newInitialData = initialData.reduce((res, {ID, FirstName}) =>
{
    res[ID] = {FirstName : FirstName};
    return res;
}, {});

console.log(newInitialData);

Using this new structure, you can make a O(n) algorithm to insert the new data that is not already there:

var initialData = {
    "1": {'FirstName': 'Sally'},
    "2": {'FirstName': 'Jim'},
    "3": {'FirstName': 'Bob'}
};

var newData = [
    {'ID': 2, 'FirstName': 'Jim'},
    {'ID': 4, 'FirstName': 'Tom'},
    {'ID': 5, 'FirstName': 'George'}
];

newData.forEach(({ID, FirstName}) =>
{
    initialData[ID] = initialData[ID] || {FirstName: FirstName};
});

console.log(initialData);

Solution 3:

I think the alternative solution proposed by @slider in the accepted answer, would be something like this:

const oldData = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 3, name: 'Mike' },
];

const newData = [
  { id: 2, name: 'Jane' },
  { id: 4, name: 'Rick' },
  { id: 5, name: 'Jim' },
];

const usersMap = newMap();

oldData.forEach(user => usersMap.set(user.id, user));

newData.forEach(user => {
  const exists = usersMap.has(user.id);
  
  if (!exists) {
    usersMap.set(user.id, user);
  }
})

usersMap.forEach(user =>console.log(user))

Post a Comment for "Javascript: Merge Two Arrays Of Objects, Only If Not Duplicate (based On Specified Object Key)"