Home > Enterprise >  Track changes in array JS
Track changes in array JS

Time:10-01

I created a script in javascript which should track all changes between 2 arrays of strings. For ex: if element was added or removed comparing with the first array.

const initial = ['test', 'color'];
const changed = ['5'];

const checkArrDiff = (initialArr, changedArr) => {
  const newElements = [];
  const removedElements = [];

  const getDiff = changedArr.reduce((acc, item, idx) => {
    if (!initialArr.includes(item)) {
      newElements.push(item)
      acc.new = newElements
    }

    if (!changedArr.includes(initialArr[idx])) {
      removedElements.push(initialArr[idx])
      acc.removed = removedElements
    }

    return acc;
  }, {})

  return getDiff;
}

console.log(checkArrDiff(initial, changed))

In the case above I expect the next result:

{
 "new": [
     "5"
  ],
 "removed": [
     "test", "color"
  ]
}

At the moment I get the wrong result. Who can help to fix the code?

CodePudding user response:

UPDATED ANSWER

For example we have two arrays arr1 and arr2.

arr1 = ["a", "b", "c"];
arr2 = ["b", "d"];

In above example arrays I have removed a,c and added d, but in my old code it will not give exact result what we expected, because when we remove a than next element b will move to 0 index so my old code will assume b as new element, but is just had changed it's index.

Here I have solved that by inserting undefined value at unmatched value position with spice function.

Now it will detect duplicated and real value. please recheck with multiple example arrays.

// new example to check does it work well or not
let initial = ["a", "b", "c"];
let changed = ["b", "d"];

console.log(getDifference(initial, changed));

// main function
function getDifference(array1, array2) {
    let result = {removed:[], new:[]};

    array1.filter((item, index) => item !== array2[index] ? (result.removed.push(item) && array2.splice(index, 0, undefined)) : null);
    array2.filter((item, index) => (item !== array1[index] && item !== undefined) ? (result.new.push(item)) : null);

    return result;
}

OLD ANSWER

It will give accurate result by matching both index number and value.

const initial = ['test', 'color'];
const changed = ['5'];

console.log(getDifference(initial, changed));

function getDifference(array1, array2) {
    let result = {removed:[], new:[]};

    array1.filter((item, index) => item !== array2[index] ? (result.removed.push(item)) : null);
    array2.filter((item, index) => item !== array1[index] ? (result.new.push(item)) : null);

    return result;
}

CodePudding user response:

The problem is you iterate over the changed array which has 1 index while you try to check 2 indexes of the initial array.

You can simplify your logic though. I think this is what you want.

With just 2 array filter calls you can define the removed and new elements.

const initial = ['test', 'color', 'both'];
const changed = ['5', 'both'];

const checkArrDiff = (initialArr, changedArr) => {
  return {
    new: changed.filter((item) => !initial.includes(item)),
    removed: initial.filter((item) => !changed.includes(item))
  }
}

console.log(checkArrDiff(initial, changed))

CodePudding user response:

Well, I would use a simple loop for that and not a reduce for reasons that jabaa pointed out

function checkArrDiff(before,after){
  var toReturn={new:[],removed:[]}
  var extras={new:[],removed:[]}
  //useless check removed by sensible suggestion by jabaa
  if(before.length<after.length){ //definitely new things
    for(let i=before.length;i<after.length;i  ){
      extras.new.push(after[i])
    }
  }
  else if(after.length<before.length){ //definitely removed things
    for(let i=after.length;i<before.length;i  ){
      extras.removed.push(before[i])
    }
  }
  var length=after.length>before.length?before.length:after.length //lowest length between the 2
  for(let i=0;i<length;i  ){
    if(before[i]!=after[i]){
      toReturn.new.push(after[i])
      toReturn.removed.push(before[i])
    }
  }
  toReturn.new.push(...extras.new)
  toReturn.removed.push(...extras.removed)
  return toReturn
}

//example
console.log(checkArrDiff(['test', 'color'],['5']))

CodePudding user response:

Here is my solution based on @Mark Baijens solution

/**
 * @param initialArr {string[]}
 * @param changedArr  {string[]}
 * @returns {{
 * newEntry: string[]
 * removedEntry: string[]
 * }}
 */
const checkArrDiff = (initialArr, changedArr) => {
    let newEntry = changedArr.filter((item) => !initialArr.includes(item));
    let removedEntry = initialArr.filter((item) => !changedArr.includes(item));

    if (!(newEntry.length && removedEntry.length)){
        const difference = Math.abs(initialArr.length - changedArr.length);

        if (initialArr.length - changedArr.length === 0){
            return {
                newEntry: [],
                removedEntry: []
            }
        } else if (initialArr.length - changedArr.length > 0){
            for (let i = 0; i < difference; i  ) {
                newEntry.push(initialArr[0])
            }
        } else {
            for (let i = 0; i < difference; i  ) {
                removedEntry.push(initialArr[0])
            }
        }
    }

    return {
        newEntry,
        removedEntry
    }
}


console.log(checkArrDiff(['one', 'two', 'both'], ['three', 'both']))

console.log(checkArrDiff(['both', 'both', 'both'], ['both', 'both']))

console.log(checkArrDiff(['both', 'both', 'both'], ['both', 'both', 'both', 'both']))

  • Related