比较两个数组,并通过使用javascript保留现有对象来更新新值
下面是我的两个数组。我想比较它们,结果数组应该包含更新的值。Id是常见的。。 阵列跨越n个级别,即没有固定级别 第一个数组,即更新前的数组比较两个数组,并通过使用javascript保留现有对象来更新新值,javascript,arrays,Javascript,Arrays,下面是我的两个数组。我想比较它们,结果数组应该包含更新的值。Id是常见的。。 阵列跨越n个级别,即没有固定级别 第一个数组,即更新前的数组 var parentArray1=[ { "id": 1, "name": "test", "context": [ { "id": 1.1, "name": "test 1.1" }
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.更新现有项目
作为这两个操作的结果,我将在不同的数组中获得更改的值。。
即
现在,我已经编写了一个通用函数,该函数在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,“名称”:“test1”,“上下文”:[{“id”:1.1,“名称”:“Changed test 1.1”}],{“id”:5,“名称”:“test5”}];
函数插入(数组、数据){
功能iter(阵列){
array.forEach(函数(a){
如果(!('id'在a中)){
返回;
}
如果(o[a.id]!==a){
o[a.id]=a;
}
Object.keys(a).forEach(函数(k){
isArray(a[k])&iter(a[k]);
});
});
}
var o={};
iter(阵列);
data.forEach(函数(a){
if(o[a.id]){
Object.keys(a).forEach(函数(k){
o[a.id][k]=a[k];
});
返回;
}
数组。推送(a);
});
}
插入(parentArray1,changedArray);
document.write(“”+JSON.stringify(parentArray1,0,4)+’代码>这是我想到的:
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;
}
功能sameKeys(o1、o2、按键){
对于(变量i=0;i1)
抛出“为同一组合键找到多个可能的对象”
阵列拼接(索引[0],1);
}
}
功能比较阵列(a1、a2、键阵列){
a2.forEach(功能(it2){
var it1s=a1.过滤器(功能(it){
返回sameKeys(it2、it、keyArray);
});
var-it1;
如果(!it1s.长度){
it1=克隆(it2);
a1.推动(it1);
}否则{
如果(it1s.length>1)
抛出“为同一组合键找到多个可能的对象”
it1=it1s[0];
扩展(it1、it2、keyArray);
}
如果(it2.移除的ID){
it2.removedIds.forEach(函数(ids){
removeFromArray(a1、ID、keyArray);
});
}
});
}
与comparararray(parentArray1,changedArray,['id'])一起使用代码>
请注意,它不适用于包含函数的对象。另外,如果数组很大,可能更好的解决方案是按键对两个数组进行排序,然后始终从最后找到的对象开始查找。我现在只有这些了
用Nina的一些概念和一些代码的清理更新了它
据我所知,您只想添加属性。所以扩展({a:{b:2}},{a:{c:3}})将导致{a:{b:2,c:3}}。如果这不是你想要的,让我知道
我还添加了删除ID的功能。如果数组中的任何对象包含形式为[{id:4},{id:5}]
的removedid
数组,则具有这些id的项将被删除
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);
});
}
});
}
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;
}