比较两个数组,并通过使用 javascript 保留现有对象来更新新值
Compare two arrays and update with the new values by keeping the existing objects using javascript
下面是我的两个数组。我想比较它们,结果数组应该包含更新的值。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;
}
相关文章:
- 如何将字符串拆分为字符,但在javascript中保留空格
- 如何在使用JavaScript或jQuery刷新父页面后保留iframe-src
- Javascript和RegEx:拆分并保留分隔符
- 在页面之间保留 JavaScript 值
- 在页面刷新后保留 JavaScript 变量值
- 在页面发布到服务器并返回错误后保留 javascript 更改
- 如何在保留 JavaScript 调试器功能的同时进行优雅的异常处理
- 我什么时候应该在html文件上保留Javascript
- 在提交 HTML 表单后保留 JavaScript 中的 innerHTML 值
- 如何保留javascript变量,即使我重新加载或重定向到任何其他页面
- 如何在页面更改时保留Javascript状态
- 删除字符串的前半部分,但保留javascript或jquery的后半部分
- 如何保留javascript工具上下
- 在粘贴到文本区域时保留javascript字符串的换行符
- 返回值并保留javascript对象的成员
- 如何保留JavaScript变量,而PayPal的工作
- React-如何在服务器端渲染时保留javascript
- asp.net mvc-在.net mvc中保留javascript状态
- 是否有任何主流浏览器不保留JavaScript对象中的插入顺序
- 如何在页面刷新时保留 javascript 数组