this.jind
this.jind

Reputation: 349

How to compare two arrays and add/remove elements depending on their difference?

Let's say I have two arrays, where array1 is always changing:

First case:

array1 = [1, 2, 3, 4, 5] 
array2 = [1, 2, 3]

How can I compare them and add 4 and 5 into array2? I am getting the difference between them doing:

let difference = array1.filter(x => !array2.includes(x));

and then doing array2.push(difference), so array2 is now equal to array1, right?

Second case:

array1 = [1, 2, 8, 9] 
array2 = [1, 2, 3]

So now I need to remove 3 from array2, and add 8 and 9, how can I do this?

EDIT: I need this because I'm getting array1 from a server(they are chats) and it's dynamically changing every 5 sec, and this is problem. I need to keep the elements I already have so they won't "update" and only change the one getting deleted or added. Hope this makes sense.

Upvotes: 1

Views: 5508

Answers (6)

gianoseduto
gianoseduto

Reputation: 194

First case will not work as aspectedlooking at the code,

to achive what you want you have to write:

difference.forEach((x) => array2.push(x));

instead of:

array2.push(difference)

for the second one if you want to remove a record in array2 because is missing in array1 you need to control each value of array2 in array1 and remove if not exists by ID

var array1 = [1, 2, 8, 9]; 
var array2 = [1, 2, 3];

//here i build difference2 collecting the value of array2 that miss on array1
let difference2 = array2.filter((x) => !array1.includes(x));

//here with splice and indexOf i remove every value collected before
difference2.forEach((x) => array2.splice(array2.indexOf(x), 1));

//following code is to add the 8 and 9 
let difference = array1.filter((x) => !array2.includes(x));
difference.forEach((x) => array2.push(x));

console.log(array2);
//the result [1,2,8,9]

Upvotes: 1

Guerric P
Guerric P

Reputation: 31815

You could do like this if you want to mutate array2:

let array1 = [1, 2, 8, 9];
let array2 = [1, 2, 3];
let valuesToAdd = array1.filter(x => !array2.includes(x));
let indexesToDelete = Object.entries(array2).filter(([, x]) => !array1.includes(x)).map(([i]) => i);

// Reverse iteration to preserve indexes while removing items
indexesToDelete.reverse().forEach(i => array2.splice(indexesToDelete[i], 1));
   
array2.push(...valuesToAdd);

console.log(array2);

Upvotes: 0

choz
choz

Reputation: 17858

I would avoid much built-in or third party compare functions since I am not sure what I am dealing with. This could be refactored and optimized more if the array1 is guaranteed to have an ordered list.

let localArray = [1, 2, 3, 4, 5],
    lastServerArray = [];

/**
 * Compares "fromArr" to "targetArr"
 * @param fromArr Array of elements
 * @param targetArr Array of elements
 * @returns List of elements from "fromArr" that do not happen in "targetArr"
 */
const compArr = (fromArr, targetArr) => {
    const result = [];
    for (let i = 0, len = fromArr.length; i < len; i++) {
        const elem = fromArr[i],
            targetIdx = targetArr.indexOf(elem);

        if (!~targetIdx && !~result.indexOf(elem)) {
            // Element do not exist in "targetArr" and in current "result"
            result.push(elem);
        }
    }

    return result;
}


const updateLocalArray = (serverArray = []) => {
    if (JSON.stringify(lastServerArray) === JSON.stringify(serverArray)) {
        console.log('Nothing changed from server, skip updating local array');
        return localArray;
    }

    lastServerArray = serverArray;

    const notExistentLocalElems = compArr(serverArray, localArray), // Elements that do not exists in local array
        notExistentServerElems = compArr(localArray, serverArray); // Elements that do not exists in server array

    // Do something to those "notExistentLocalElems" or "notExistentServerElems"
    // ---

    // Sync server array to local array

    // Remove elements that is not on server.
    localArray = localArray.filter(elem => !~notExistentServerElems.indexOf(elem));
    console.log('These elements removed from localArray', notExistentServerElems);

    // Append elements that is on server.
    localArray.push(...notExistentLocalElems);
    console.log( 'These elements added into localArray', notExistentLocalElems);

    return localArray;
}

updateLocalArray([1, 2, 3]);
console.log(`1. server sends [1, 2, 3] -- local becomes`, localArray);

updateLocalArray([3, 4, 5, 6]);
console.log(`2. server sends [3, 4, 5, 6] -- local becomes`, localArray);

updateLocalArray([5, 5, 4, 2, 7]);
console.log(`3. server sends [5, 5, 4, 2, 7] -- local becomes`, localArray);

updateLocalArray([0, 0, 1, 2]);
console.log(`4. server sends [0, 0, 1, 2] -- local becomes`, localArray);

Upvotes: 0

Reyno
Reyno

Reputation: 6505

Just use another filter and combine the two arrays.

const array1 = [1, 2, 8, 9];
let array2 = [1, 2, 3];

const inArrOne = array1.filter(x => !array2.includes(x));
const inBothArr = array2.filter(x => array1.includes(x));

array2 = [...inBothArr, ...inArrOne];

console.log(array2);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386604

You could take a Set and delete seen items and add the rest to the array.

const
    array1 = [1, 2, 8, 9],
    array2 = [1, 2, 3],
    set1 = new Set(array1);
let i = array2.length; 

while (i--) if (!set1.delete(array2[i])) array2.splice(i, 1);
array2.push(...set1);

console.log(array2);

Upvotes: 0

sourav satyam
sourav satyam

Reputation: 986

let array1 = [1, 2, 3, 4, 5];
let array2 = [1, 2, 3];

let filteredArray = array2.filter((a) => array1.includes(a));
let secFilteredArray = array1.filter((a) => !filteredArray.includes(a));

console.log(filteredArray.concat(secFilteredArray));

Upvotes: 0

Related Questions