Best performance operations for JS Array NEQ operation

Viewed 44

Im currently tackling the optimization of combining two arrays. The problem is the following:

  • I have 2 Arrays of different sizes with Array A beeing smaller in all cases that Array B (Most of the time with different magnitude)
  • Array A contains objects in with two ID's
[{
    AccountID: "1234141",
    ContactID: "1256612"
},{
    AccountID: "2346278",
    ContactID: "2378898"
}, ...]
  • Array B contains objects with simple key value pairs in it. Every object also has one or two of the ID's contained in Array A
[{
    AccountID: "1234141",
    Name: "Peter Peterson",
    Contact: "Mail",
    ...
  },
  {
    ContactID: "2378898",
    Name: "Max Mustermann",
    Contact: "Phone",
    ...
  },
  ...
]
  • Before the execution of the algorithm the name of the ID field that should be used as a comparison is known (e.g. AccountID, ContactID). In the code example this parameter is called "idKeyName".
  • The algorithm should compute a Not Equal operator on the two arrays. As a result it should return Array B without the elements of Array A that have the same ID in the field specified above.

The legacy code was this:

jQuery.each(arrayA, function (index, value, array) {
    if (arrayA[index][idKeyName] !== "" && list.indexOf(arrayA[index][
            idKeyName
        ]) === -1)
        list.push(arrayA[index][idKeyName]);
});

jQuery.each(arrayB, function (index, value, array) {
    if (list.indexOf(arrayB[index][idKeyName]) === -1) {
        results.push(value);
    }
});

As you can see the performance is pretty poor as the Arrays have to be run through twice.
My improvement of the code led me to this:

arrayA.forEach(function (oItem) {
    var iIndex = arrayB.findIndex(function (x) {
        return oItem[idKeyName] === x[idKeyName];
    });
    if (iIndex !== -1) {
        arrayB.splice(iIndex, 1);
    }
});

As ArrayA is smaller than ArrayB i run through it instead of e.g. filtering ArrayB, to hopefully have the least amount of repetitions. If I find that the current element is connected to an element in ArrayB (same ID's), I splice it out of ArrayB. At the end I just have to return ArrayB as the result.

Question: Is there a better (faster performance) way of computing this NEQ operator on both arrays?

Thank you for your help!

1 Answers

The problem in both solutions is the need to iterate array A for every item in array B.

Instead create a Set from the 1st array (A) relevant ids, and then filter the 2nd array (b) by checking that the relevant id doesn't appear in the Set:

const fn = key => (arrA, arrB) => {
  const arrASet = new Set(A.map(o => o[key]))
  
  return arrB.filter(o => !arrASet.has(o[key]))
}

const A = [{"AccountID":"1234141","ContactID":"1256612"},{"AccountID":"2346278","ContactID":"2378898"}]
const B = [{"AccountID":"1234141","Name":"Peter Peterson","Contact":"Mail"},{"ContactID":"2378898","Name":"Max Mustermann","Contact":"Phone"}]

const filterByAccountID = fn('AccountID')
const filterByContactID = fn('ContactID')

console.log(filterByAccountID(A, B))
console.log(filterByContactID(A, B))

Related