Search code examples
javascriptarrayslodash

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.


Solution

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