比较两个数组并通过使用javascript保留现有对象来用新值更新 [英] Compare two arrays and update with the new values by keeping the existing objects using javascript

查看:56
本文介绍了比较两个数组并通过使用javascript保留现有对象来用新值更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  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,
名称:测试
}
]

我执行的操作是



1.A填充新项目
2.更新现有项目



由于这两个操作,更改后的值将在另一个数组中。 b $ b,即

  varchangedArray = 

[
{
id:1,1,
name: test1,
context:[
{
id:1.1,
name :更改后的测试1.1
}
]
},
{
id:5,
name: test5
}
]

现在,我编写了一个遍历parentArray1和使用独特的属性我需要添加一个新项目,如果该项目在 changedArray 中,或者在任何级别更新现有项目



结果数组应为..

  [
{
id:1,
name: test,
context:[
{
id:1.1,
name:更改的测试1.1
}
]
},
{
id:2,
name: test
},
{
id:3,
name: test,
context:[
{
id:3.1,
name :测试3.1
}
]
},
{
id:4,
name: test
},
{
id:5,
name: test5
}
]

泛型函数:

  compareArray(parentArray1, changeArray,[ id]); 

函数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)
}否则{
/循环属性名称以进行验证/
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);
}
}
}
})
}

});
});

/将新项目插入源数组/
newItem.map(function(item){
array1.push(item);
});
console.log( Compare之后: + array1);
}


解决方案

这就是我的想法

  function sameKeys(o1,o2,keys){
for(var i = 0; i< keys.length; i ++){
var key = keys [i];
if(!o1.hasOwnProperty(key)||!o2.hasOwnProperty(key))
抛出比较对象没有键 +键;
if(o1 [key]!== o2 [key])
返回false;
}
返回true;
}

函数isNothing(o){
return typeof(o)===未定义 || o === null;
}

//如果对象具有作为属性的功能
函数clone(o){
if(isNothing(o))
//返回o;
return JSON.parse(JSON.stringify(o));
}

函数extend(o1,o2,键){
if(isNothing(o2))
return;
if(isNothing(o1))
throw(第一个参数不能为空);
if(typeof(o1)!='对象'|| typeof(o2)!='对象')
抛出(扩展仅对对象有效);
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;
中断;
默认值:
throw'不支持的属性类型:'+ typeof(newVal);
}
}
} else {
o1 [key] = clone(newVal) ;
}
});
}

函数removeFromArray(arr,ids,keyArray){
var index = [];
var it1s = arr.forEach(函数(it,idx){
if(sameKeys(ids,it,keyArray)){
index.push(idx);
}否则{
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'找到同一键组合的多个可能对象'
arr.splice(indexes [ 0],1);
}
}

函数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);
}否则{
if(it1s.length> 1)
throw'found同一键组合的多个可能对象'
it1 = it1s [0];
extend(it1,it2,keyArray);
}
if(it2.removedIds){
it2.removedIds.forEach(function(ids){
removeFromArray(a1,ids,keyArray);
});
}
});

}

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



请注意,它不适用于包含函数的对象。同样,如果数组很大,也许更好的解决方案是按键对两个数组进行排序,然后始终从最后找到的对象开始查找。



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



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



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


Below are my two arrays .I want to compare them and the resultant array should contain the updated values.Id's are common.. The arrays spans to n levels ie., there is no fixed levels..

The first array ie., the array before updation..

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

The operations that i performed are

1.Adding a new Item 2.Updating an existing item

As a result of these two operations the changed values I will be getting in a different array.. ie.,

var changedArray=

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

Now I have written a generic function that loops through the parentArray1 and using the unique propertiesI need to either add a new item,if the item is there in the changedArray or update an existing item at any level

The resultant array should be ..

[
    {
        "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"
    }
]

Generic function:

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);
        }

解决方案

This is what I came up with:

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);
            });
        }
    });

}

Use it with compareArray(parentArray1,changedArray,['id']);

Note that it would not work with objects that contain functions. Also, if the arrays would be large, perhaps a better solution is to sort both arrays by key, then always look from the last found object up. That's all I got for now.

Updated it with some concepts from Nina and some clearing of the code.

As I understood it, you only want to add properties. So extend({a: {b: 2}},{a:{c:3}}) will result in {a: {b:2,c:3}}. If this is not what you wanted, let me know.

I also added functionality for removing ids. If any of the objects in the array contains a removedIds array of the form [{id: 4},{id: 5}] then the items with those ids will be removed from the original array.

这篇关于比较两个数组并通过使用javascript保留现有对象来用新值更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆