0

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?

Not A Robot
2,7002 gold badges20 silver badges37 bronze badges
asked Oct 1, 2021 at 11:40
4
  • 6
    changedArr has one element. changedArr.reduce calls the callback once with idx set to 0. It's never called with idx set to 1. Commented Oct 1, 2021 at 11:47
  • Also, what is the expected output if the initial and changed arrays are: ['test', 'color'] and ['test', 5]? Commented Oct 1, 2021 at 11:48
  • 1
    What's the expected result for const initial = ['test', 'test']; const changed = ['test']; and const initial = ['test']; const changed = ['test', 'test'];. You probably have to overthink your approach. Commented Oct 1, 2021 at 11:50
  • The first problem can be solved with two separate filters instead of one reduce: jsfiddle.net/hbp8r3nk but that doesn't solve the second problem I described. Commented Oct 1, 2021 at 11:57

4 Answers 4

2

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;
}

answered Oct 1, 2021 at 12:26
Sign up to request clarification or add additional context in comments.

Comments

1

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))

answered Oct 1, 2021 at 11:55

3 Comments

"I created a script in javascript which should track all changes between 2 arrays of strings." Your script doesn't work for const initial = ['test', 'test', 'test']; const changed = ['test', 'test'];
@jabaa The op didn't mention duplicates. If he needs to track this the occurences would need to be counted.
OP described the problem: "track all changes" (duplicates are part of "all changes") and posted one example. Of course, one example can't contain all possible cases. OP didn't mention upper case letters and the example doesn't contain upper case letters but it should be obvious that it should also work with upper case letters.
0

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']))

answered Oct 1, 2021 at 12:06

5 Comments

As long as there is no cleaner solution there shouldn't be a downvote for "scrappy" code.
Maybe because before==after. You can't compare arrays this way. This will always return false for two different arrays even if they contain the same elements: jsfiddle.net/t50f41da
well, if the array is the same.. there definitely won't be any changes right.. because of that im assuming they're doing like a JSON.parse(JSON.stringify(array)) to track when the array changes
[1] == [1] returns false because that's two different objects. The line if(before==after){return toReturn} doesn't make any sense because before == after will always be false in this code.
0

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']))

answered Oct 1, 2021 at 12:52

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.