Reputation: 349
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
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
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
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
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
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
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