【问题标题】:Update/add/remove object in array if exist in other array by id如果按 id 存在于其他数组中,则更新/添加/删除数组中的对象
【发布时间】:2020-07-30 11:34:04
【问题描述】:

我的 Angular 应用程序中有一个项目数组(对象的有序数组)。这些项目正在更新,新值来自服务(无序)。我需要编写一个算法来更新现有数组。我以前只是用新数组替换旧数组,但这弄乱了项目的顺序。我有以下边缘情况,其中oldArr 是我的旧项目数组,newArr 是来自服务的数组,outputoldArray 应该是什么样子:

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

这类东西我一般用lodash,但也可以是普通的JS。

【问题讨论】:

  • oldArr有什么用?并非所有newArr
  • 你保持订单的属性是什么?
  • 订单由dragula插件处理。

标签: javascript arrays lodash


【解决方案1】:

怎么样:

const output = newArray.sort((a, b) => a.id - b.id);

编辑

根据提供的说明,我研究了这个算法,它似乎产生了预期的结果

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)

【讨论】:

  • 或者只是 newArray.sort((a, b) =&gt; a.id - b.id); 不需要 if 语句
  • id 不代表订单。旧数组也可以是[{id: 65, invalid: true}, {id: 2, invalid: true}]
【解决方案2】:

我将通过转换 Map 中的数组之一来开始执行此操作。 这将大大简化 LoopUp for index。

然后相对于新创建的地图开始合并:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 2018-04-26
    • 1970-01-01
    相关资源
    最近更新 更多