Comparing Two Arrays and Grouping into Inserts and Updates

Ademo :

I am comparing two arrays and then grouping them into inserts and updates. The updates array should end up including elements that match on id == Id, but where open_balance !- DocumentAmount. The inserts array should include only elements where the id != Id. Notice I am running both through the toString() method because in my scenario one is of type String whereas the other is of type Integer from two different SQL Databases.

Now, with the code I have now, the first grouping works - via the findRecordsToUpdate() function, I get all of the elements matched correctly for the updates - which should be two elements, because these two match on id, but not on the amount:

  recordsToUpdate: [
   { Id: '333', DocumentAmount: 20 },
   { Id: '444', DocumentAmount: 10 }
  ] 

But the inserts, which is produced by the findRecordsToInsert() function, are not correct. According to my data I should end up with one element, with an Id of '555' in my recordsToUpdate array, because it's the only element with an Id not found in the other array -- i.e. it's a new record to insert. But instead I end up with 13 elements with my current code?

What am I missing here and what do I need to change to get the correct inserts populated to my recordsToInsert array?:

const sourceArr = [
  { id: 111, open_balance: 10 },
  { id: 222, open_balance: 20 },
  { id: 333, open_balance: 10 },
  { id: 444, open_balance: 20 },
]

const targetArr = [
  { Id: '111', DocumentAmount: 10 },
  { Id: '222', DocumentAmount: 20 },
  { Id: '333', DocumentAmount: 20 },
  { Id: '444', DocumentAmount: 10 },
  { Id: '555', DocumentAmount: 10 },
]

function findRecordsToUpdate () {
  if (sourceArr.length && targetArr.length) {
    let recordsToUpdate = [];
    for (let t of targetArr) {
      for (let s of sourceArr) {
        if ((t.Id.toString() == s.id.toString()) && (t.DocumentAmount != s.open_balance)) {
          recordsToUpdate.push(t);
        }
      }
    }
    console.log('recordsToUpdate: ', recordsToUpdate);
    return recordsToUpdate;
  }
};

function findRecordsToInsert () {
  if (sourceArr.length && targetArr.length) {
    let recordsToInsert = [];
    for (let t of targetArr) {
      for (let s of sourceArr) {
        if (t.Id.toString() != s.id.toString()) {
          recordsToInsert.push(t);
        }
      }
    }
    console.log('recordsToInsert: ', recordsToInsert);
    return recordsToInsert;
  }
};

findRecordsToUpdate();
findRecordsToInsert();

By the way, to clarify, my findRecordsToInsert() function should return a recordsToInsert array like this when done, as the record with an Id of 555 is the only record from the second array that doesn't exist in the first array:

recordsToInsert: [{ Id: '555', DocumentAmount: 10 }]

So, to be clear, it's just the findRecordsToInsert() function that is not working correctly at present.

avejidah :

Use a combination of Array#filter and Array#find to get your insert and update arrays out of targetArr.

'use strict';

const sourceArr = [
  { id: 111, open_balance: 10 },
  { id: 222, open_balance: 20 },
  { id: 333, open_balance: 10 },
  { id: 444, open_balance: 20 },
];

const targetArr = [
  { Id: '111', DocumentAmount: 10 },
  { Id: '222', DocumentAmount: 20 },
  { Id: '333', DocumentAmount: 20 },
  { Id: '444', DocumentAmount: 10 },
  { Id: '555', DocumentAmount: 10 },
];

// Target records with a matching source (on ID) where the amount has changed.
// Update these.
const recordsToUpdate = targetArr
  .filter(tar => sourceArr
    .find(source => source.id === Number(tar.Id) && source.open_balance !== tar.DocumentAmount));

console.log(recordsToUpdate);

// Target records that have no matching source record (i.e. new records).
// Insert these.
const recordsToInsert = targetArr
  .filter(tar => !sourceArr
    .find(source => source.id === Number(tar.Id)));

console.log(recordsToInsert);
Edit

Just for the record, in your original code the search in findRecordsToInsert is incorrect. To fix the issue, try to find each target in source and, if not found, add target to the insert array. But it's just a long-winded version of filter-find.

const sourceArr = [
  { id: 111, open_balance: 10 },
  { id: 222, open_balance: 20 },
  { id: 333, open_balance: 10 },
  { id: 444, open_balance: 20 },
]

const targetArr = [
  { Id: '111', DocumentAmount: 10 },
  { Id: '222', DocumentAmount: 20 },
  { Id: '333', DocumentAmount: 20 },
  { Id: '444', DocumentAmount: 10 },
  { Id: '555', DocumentAmount: 10 },
]

function findRecordsToInsert () {
  if (sourceArr.length && targetArr.length) {
    const recordsToInsert = [];
    for (const t of targetArr) {
      let found = false;

      for (let i = 0; i < sourceArr.length && !found; ++i) {
        if (t.Id.toString() === sourceArr[i].id.toString())
          found = true;
      }

      if (!found)
        recordsToInsert.push(t);
    }

    console.log('recordsToInsert: ', recordsToInsert);
    return recordsToInsert;
  }
};

findRecordsToInsert();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=8587&siteId=1
Recommended