比较两个数组,并通过使用 javascript 保留现有对象来更新新值

Compare two arrays and update with the new values by keeping the existing objects using javascript

本文关键字:保留 javascript 对象 新值 更新 两个 数组 比较      更新时间:2023-09-26

下面是我的两个数组。我想比较它们,结果数组应该包含更新的值。Id很常见。数组跨越 n 个级别,即没有固定级别。

第一个数组,即更新前的数组。

var parentArray1=[
    {
        "id": 1,
        "name": "test",
        "context": [
            {
                "id": 1.1,
                "name": "test 1.1"
            }
        ]
    },
    {
        "id": 2,
        "name": "test"
    },
    {
        "id": 3,
        "name": "test",
        "context": [
            {
                "id": 3.1,
                "name": "test 3.1"
            }
        ]
    },
    {
        "id": 4,
        "name": "test"
    }
]

我执行的操作是

1.添加新项目2.更新现有项目

由于这两个操作,我将在不同的数组中获得更改的值。即,

var changedArray=
       [
        {
            "id": 1,
            "name": "test1",
            "context": [
                {
                    "id": 1.1,
                    "name": "Changed test 1.1"
                }
            ]
        },
        {
            "id": 5,
            "name": "test5"
        }
    ]

现在我已经编写了一个通用函数,它循环遍历 parentArray1 并使用唯一属性我需要添加一个新项目,如果该项目在 changedArray 中,或者更新任何级别的现有项目

结果数组应该是 ..

[
    {
        "id": 1,
        "name": "test",
        "context": [
            {
                "id": 1.1,
                "name": "Changed test 1.1"
            }
        ]
    },
    {
        "id": 2,
        "name": "test"
    },
    {
        "id": 3,
        "name": "test",
        "context": [
            {
                "id": 3.1,
                "name": "test 3.1"
            }
        ]
    },
    {
        "id": 4,
        "name": "test"
    },
    {
        "id": 5,
        "name": "test5"
    }
]

通用函数:

compareArray(parentArray1, changedArray, ["id"]);
        function compareArray(array1, array2, propertyArray) {
            var newItem = new Array();
            array2.map(function(a1Item) {
                array1.map(function(a2Item) {
                    / If array loop again /
                    if (a2Item.constructor === Array) {
                        compareArray(a2Item, a1Item)
                    } else {
                        / loop the property name to validate /
                        propertyArray.map(function(property) {
                            if (a2Item[property]) {
                                if (a2Item[property] === a1Item[property]) {
                                    a2Item = a1Item
                                } else {
                                    var isAvailable = _.find(newItem, function(item) {
                                        return item[property] === a1Item[property]
                                    })
                                    if (!isAvailable) {
                                        newItem.push(a1Item);
                                    }
                                }
                            }
                        })
                    }
                });
            });
            / Insert the new item into the source array /
            newItem.map(function(item) {
                array1.push(item);
            });
            console.log("After Compare : " + array1);
        }

我建议使用临时对象来引用id,如果存在,则更新,如果不存在,则推送。

var parentArray1 = [{ "id": 1, "name": "test", "context": [{ "id": 1.1, "name": "test 1.1" }] }, { "id": 2, "name": "test" }, { "id": 3, "name": "test", "context": [{ "id": 3.1, "name": "test 3.1" }] }, { "id": 4, "name": "test" }],
    changedArray = [{ "id": 1, "name": "test1", "context": [{ "id": 1.1, "name": "Changed test 1.1" }] }, { "id": 5, "name": "test5" }];
function insert(array, data) {
    function iter(array) {
        array.forEach(function (a) {
            if (!('id' in a)) {
                return;
            }
            if (o[a.id] !== a) {
                o[a.id] = a;
            }
            Object.keys(a).forEach(function (k) {
                Array.isArray(a[k]) && iter(a[k]);
            });
        });
    }
    var o = {};
    iter(array);
    data.forEach(function (a) {
        if (o[a.id]) {
            Object.keys(a).forEach(function (k) {
                o[a.id][k] = a[k];
            });
            return;
        }
        array.push(a);
    });            
}
insert(parentArray1, changedArray);
document.write('<pre>' + JSON.stringify(parentArray1, 0, 4) + '</pre>');

这是我想到的:

function sameKeys(o1, o2, keys) {
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if (!o1.hasOwnProperty(key) || !o2.hasOwnProperty(key))
            throw 'compared objects do not have the key ' + key;
        if (o1[key] !== o2[key])
            return false;
    }
    return true;
}
function isNothing(o) {
    return typeof(o) === 'undefined' || o === null;
}
// this does not work if objects have functions as properties
function clone(o) {
    if (isNothing(o))
        return o;
    return JSON.parse(JSON.stringify(o));
}
function extend(o1, o2, keys) {
    if (isNothing(o2))
        return;
    if (isNothing(o1))
        throw ('first parameter cannot be empty');
    if (typeof(o1) != 'object' || typeof(o2) != 'object')
        throw ('extend only works on objects');
    Object.keys(o2).forEach(function (key) {
        var newVal = o2[key];
        if (o1.hasOwnProperty(key)) {
            if (isNothing(newVal)) {
                delete o1[key];
            } else
                if (Array.isArray(newVal)) {
                    compareArray(o1[key], newVal, keys);
                } else {
                    switch (typeof(newVal)) {
                    case 'object':
                        extend(o1[key], newVal, keys);
                        break;
                    case 'boolean':
                    case 'number':
                    case 'string':
                        o1[key] = newVal;
                        break;
                    default:
                        throw 'not supported property type: ' + typeof(newVal);
                    }
                }
        } else {
            o1[key] = clone(newVal);
        }
    });
}
function removeFromArray(arr, ids, keyArray) {
    var indexes = [];
    var it1s = arr.forEach(function (it, idx) {
            if (sameKeys(ids, it, keyArray)) {
                indexes.push(idx);
            } else {
                Object.keys(it).forEach(function (key) {
                    var newVal = it[key];
                    if (Array.isArray(newVal)) {
                        removeFromArray(it[key], ids, keyArray);
                    }
                });
            }
        });
    if (indexes.length) {
        if (indexes.length > 1)
            throw 'found multiple possible objects for the same key combination'
            arr.splice(indexes[0], 1);
    }
}
function compareArray(a1, a2, keyArray) {
    a2.forEach(function (it2) {
        var it1s = a1.filter(function (it) {
                return sameKeys(it2, it, keyArray);
            });
        var it1;
        if (!it1s.length) {
            it1 = clone(it2);
            a1.push(it1);
        } else {
            if (it1s.length > 1)
                throw 'found multiple possible objects for the same key combination'
                it1 = it1s[0];
            extend(it1, it2, keyArray);
        }
        if (it2.removedIds) {
            it2.removedIds.forEach(function (ids) {
                removeFromArray(a1, ids, keyArray);
            });
        }
    });
}

compareArray(parentArray1,changedArray,['id']);一起使用

请注意,它不适用于包含函数的对象。此外,如果数组很大,也许更好的解决方案是按键对两个数组进行排序,然后始终从最后一个找到的对象向上看。这就是我现在得到的全部。

用 Nina 的一些概念和一些代码清除对其进行了更新。

据我了解,您只想添加属性。So extend({a: {b: 2}},{a:{c:3}}) 将产生 {a: {b:2,c:3}}.如果这不是您想要的,请告诉我。

我还添加了删除 id 的功能。如果数组中的任何对象包含表单[{id: 4},{id: 5}]removedIds数组,则具有这些 id 的项目将从原始数组中删除。

对代码稍作修改,以满足您的条件。试试吧!

function compareArray(originalArray, destinationArray, propertyArray) {
            var newItem = new Array(), processedItem = new Array();
            for (var i = 0; i < originalArray.length; i++) {
                var sourceElement = originalArray[i];
                for (var j = 0; j < destinationArray.length; j++) {
                    var destinationElement = destinationArray[j];
                    var isUpdated = false;
                    if (sourceElement.constructor === Array) {
                        compareArray(sourceElement, destinationElement, propertyArray);
                    } else {
                        /* loop the property name to validate */
                        propertyArray.map(function(property) {
                            if (sourceElement[property]) {
                                if (sourceElement[property] === destinationElement[property]) {
                                    originalArray[i] = _.clone(destinationElement);
                                    isUpdated = true;
                                    return;
                                } else {
                                    var isAvailable = _.find(newItem, function(item) {
                                        return item[property] === destinationElement[property];
                                    });
                                    if (!isAvailable) {
                                        var isAlreadyProcessed = _.find(processedItem, function(item) {
                                            return item[property] === destinationElement[property];
                                        });
                                        if(!isAlreadyProcessed){
                                            newItem.push(destinationElement);
                                        }
                                    }
                                }
                            }
                        });
                    }
                    if (isUpdated === true) {
                        break;
                    }
                }
                processedItem.push(sourceElement);
            }
                newItem.map(function(item) {
                    originalArray.push(item);
                });
                return originalArray;
        }