简体   繁体   中英

Update/add/remove object in array if exist in other array by id

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.

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)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM