Reputation: 6752
I have in my angular app an array of items (ordered array of objects). Those items are getting updated and the new values are coming from a service (out of order). I need to write an algorithm to update the existing array. I used to just replace the old array with the new one, but this messed up the order of items. I have the following edge cases, where oldArr
is my old array of items, the newArr
is the array comming from service and the output
, how the oldArray
should look like:
const oldArr = [{id: 1, invalid: true}];
const newArr = [{id: 1, invalid: false}];
Output: [{id: 1, invalid: false}]
const oldArr = [{id: 1, invalid: true}];
const newArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
Output: [{id: 1, invalid: true}, {id: 2, invalid: true}]
const oldArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
const newArr = [{id: 1, invalid: true}];
Output: [{id: 1, invalid: true}]
const oldArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
const newArr = [{id: 2, invalid: true}, {id: 1, invalid: true}];
Output: [{id: 1, invalid: true}, {id: 2, invalid: true}]
const oldArr = undefined
const newArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
Output: [{id: 1, invalid: true}, {id: 2, invalid: true}]
const oldArr = [{id: 1, invalid: true}];
const newArr = undefined;
Output: undefined
const oldArr = [{id: 65, invalid: true}, {id: 2, invalid: true}];
const newArr = [{id: 2, invalid: true}, {id: 65, invalid: true}];
Output: [{id: 65, invalid: true}, {id: 2, invalid: true}]
For this kind of stuff I usually use lodash, but it can be a plain JS as well.
Upvotes: 0
Views: 258
Reputation: 3
I will start doing this by converting One of the Array in Map. This would greatly simplify the LoopUp for index.
Then Start Merging with respect to the Newly Created Map:
const oldArr = [{id: 65, invalid: true}, {id: 2, invalid: true}];
const newArr = [{id: 2, invalid: true}, {id: 65, invalid: true}];
function mergeArray(oldArr, newArr) {
//Return if Any Array is Invalid
if (!oldArr || !newArr) return newArr;
//NewArray_Map: For Easy Value LookUp, Retrieval
let newMap = new Map(newArr.map(i => [i.id, i.invalid]));
//OLD_Array CleanUp : Remove values not present in New Array
oldArr = oldArr.filter((old) => newMap.has(old.id));
//Declare Temperory Array to Store Processed Values
let compltedVal = [];
//Update Existing OLD_Array Values
oldArr.forEach((oObj) => {
if (newMap.has(oObj.id)) {
oObj.invalid = newMap.get(oObj.id);
compltedVal.push(oObj.id);
}
});
//Remove Already Processed Values before Concat
newArr = newArr.filter((obj) => !compltedVal.includes(obj.id));
//Concat : Updated_OLD_Array + NEWLY_Added_Elements_Array
return oldArr.concat(newArr);
}
console.log(mergeArray(oldArr, newArr));
//result = [{id: 65, invalid: true}, {id: 2, invalid: true}]
Upvotes: 0
Reputation: 1379
what about :
const output = newArray.sort((a, b) => a.id - b.id);
EDIT
Following the clarifications provided, I worked on this algorithm which seems to produce the expected result
function merge(oldArray, newArray) {
if(!Array.isArray(newArray)) {
return newArray;
}
if(!Array.isArray(oldArray)) {
return newArray;
}
//Find values that are in newArr but not in oldArr
var diff = newArr.filter(function(obj) {
return !oldArray.some(function(obj2) {
return obj.id == obj2.id;
});
});
// Compare elements and replace matches
for(let i = 0; i < oldArray.length; i += 1) {
for(let j = 0; j < newArray.length; j += 1) {
if(oldArray[i].id === newArray[j].id) { // Replace content if ids match
oldArray[i] = {...newArray[j]}
break;
} else if(j === newArray.length -1) { // If oldArray[i] doesnt match anything in newArray, delete it
oldArray.splice(i, 1);
i -= 1;
}
}
}
return oldArray.concat(diff);
}
let oldArr = [{id: 1, invalid: true}];
let newArr = [{id: 1, invalid: false}];
let output = merge(oldArr, newArr)
console.log('output 1', output)
oldArr = [{id: 1, invalid: true}];
newArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
output = merge(oldArr, newArr)
console.log('output 2', output)
oldArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
newArr = [{id: 1, invalid: true}];
output = merge(oldArr, newArr)
console.log('output 3', output)
oldArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
newArr = [{id: 2, invalid: true}, {id: 1, invalid: true}];
output = merge(oldArr, newArr)
console.log('output 4', output)
oldArr = undefined
newArr = [{id: 1, invalid: true}, {id: 2, invalid: true}];
output = merge(oldArr, newArr)
console.log('output 5', output)
oldArr = [{id: 1, invalid: true}];
newArr = undefined;
output = merge(oldArr, newArr)
console.log('output 6', output)
oldArr = [{id: 65, invalid: true}, {id: 2, invalid: true}];
newArr = [{id: 2, invalid: true}, {id: 65, invalid: true}];
output = merge(oldArr, newArr)
console.log('output 7', output)
Upvotes: 1