JavaScript 中通过公共属性“交叉”两个 JSON 对象数组的最佳方式
Best way in JavaScript to "intersect" two arrays of JSON objects by common property?
假设我们有两个数组,arr1
和 arr2
,由 JSON 对象组成,它们共享一个公共属性id
:
var arr1 = [{'id':10,'value1':'a1'},
{'id':11,'value1':'b1'},
{'id':12,'value1':'c1'},
{'id':13,'value1':'d1'},
{'id':14,'value1':'e1'}];
var arr2 = [{'id':100000,'value2':'a2'},
{'id':11,'value2':'b2'},
{'id':100002,'value2':'c2'},
{'id':100003,'value2':'d2'},
{'id':14,'value2':'e2'}];
我需要从 ID 匹配的两个数组中提取"值"项,即预期的输出将是:
[0] value1: b1, value2: b2
[1] value1: e1, value2: e2
我有一个嵌套循环解决方案的工作示例(见下文),但它很慢(想象一下这些数组很大,每次迭代都涉及一些 UI 操作),所以我真的希望有一个更优雅、更快速的解决方案。
var arr1 = [{'id':10,'value1':'a1'},
{'id':11,'value1':'b1'},
{'id':12,'value1':'c1'},
{'id':13,'value1':'d1'},
{'id':14,'value1':'e1'}];
var arr2 = [{'id':100000,'value2':'a2'},
{'id':11,'value2':'b2'},
{'id':100002,'value2':'c2'},
{'id':100003,'value2':'d2'},
{'id':14,'value2':'e2'}];
for (var i = 0, len1 = arr1.length; i < len1; i++) {
for (var j = 0, len2 = arr2.length; j < len2; j++) {
if (arr1[i].id === arr2[j].id) {
theFunction(arr1[i].value1, arr2[j].value2);
break;
}
}
}
function theFunction(value1, value2) {
var div = document.getElementById('out');
div.innerHTML += '<br />value1: ' + value1 + ', value2: ' + value2;
}
<div id='out'>
</div>
构建要value1
的id
映射,然后迭代arr2
匹配它们:
var arr1 = [{'id':10,'value1':'a1'},
{'id':11,'value1':'b1'},
{'id':12,'value1':'c1'},
{'id':13,'value1':'d1'},
{'id':14,'value1':'e1'}];
var arr2 = [{'id':100000,'value2':'a2'},
{'id':11,'value2':'b2'},
{'id':100002,'value2':'c2'},
{'id':100003,'value2':'d2'},
{'id':14,'value2':'e2'}];
var value1s = {};
arr1.forEach(function(item) {
value1s[item.id] = item.value1;
});
arr2.forEach(function(item) {
if (item.id in value1s) {
theFunction(value1s[item.id], item.value2);
}
});
function theFunction(value1, value2) {
var div = document.getElementById('out');
div.innerHTML += '<br />value1: ' + value1 + ', value2: ' + value2;
}
<div id='out'>
</div>
您可以先构建简单的 id
数组,然后更简单地使用它们,如下所示:
var arr1 = [{'id':10,'value1':'a1'},
{'id':11,'value1':'b1'},
{'id':12,'value1':'c1'},
{'id':13,'value1':'d1'},
{'id':14,'value1':'e1'}];
var arr2 = [{'id':100000,'value2':'a2'},
{'id':11,'value2':'b2'},
{'id':100002,'value2':'c2'},
{'id':100003,'value2':'d2'},
{'id':14,'value2':'e2'}];
var tmp1 = arr1.map(function(obj) {
return obj.id;
});
var tmp2 = arr2.map(function(obj) {
return obj.id;
});
tmp1.forEach(function(id1, index1) {
var index2 = tmp2.indexOf(id1);
if (index2 > -1) {
document.getElementById('out').innerHTML +=
'<br />value1: ' + arr1[index1].value1 +
', value2: ' + arr2[index2].value2;
}
});
<div id='out'>
</div>
我会提取id
并将其用作对象的键。这样比较两者之间的存在将快得多。
var id1 = arr1.reduce(function(p,v,i){p[v.id] = i; return p;}, {}),
id2 = arr2.reduce(function(p,v,i){p[v.id] = i; return p;}, {});
for(key in id1){
if (id2.hasOwnProperty(key)){
var element1 = arr1[id1[key]],
element2 = arr2[id2[key]];
theFunction(element1.value1, element2 .value2);
}
}
https://jsfiddle.net/gaby/1ej0jxpq/2/演示
我认为循环中最慢的部分将是DOM操作。如果你把它移到循环之外,只是在循环中构建一个字符串,它应该会快得多......
var arr1 = [{'id':10,'value1':'a1'},
{'id':11,'value1':'b1'},
{'id':12,'value1':'c1'},
{'id':13,'value1':'d1'},
{'id':14,'value1':'e1'}];
var arr2 = [{'id':100000,'value2':'a2'},
{'id':11,'value2':'b2'},
{'id':100002,'value2':'c2'},
{'id':100003,'value2':'d2'},
{'id':14,'value2':'e2'}];
// create a string to build results
var out = '';
for (var i = 0, len1 = arr1.length; i < len1; i++) {
for (var j = 0, len2 = arr2.length; j < len2; j++) {
if (arr1[i].id === arr2[j].id) {
// build results string in loop
out += '<br />value1: ' + arr1[i].value1 + ', value2: ' + arr2[j].value2;
break;
}
}
}
// append results to dom
document.getElementById('out').innerHTML += out;
<div id='out'>
</div>
假设顺序不重要,您可以采用不同的方法,通过连接、排序,然后在单个循环中比较相邻的值。
var arr1 = [{'id':10,'value1':'a1'},
{'id':11,'value1':'b1'},
{'id':12,'value1':'c1'},
{'id':13,'value1':'d1'},
{'id':14,'value1':'e1'}];
var arr2 = [{'id':100000,'value2':'a2'},
{'id':11,'value2':'b2'},
{'id':100002,'value2':'c2'},
{'id':100003,'value2':'d2'},
{'id':14,'value2':'e2'}];
// join the two arrays, and sort them so you can loop through
// once comparing current to last value
arr1.concat(arr2).sort(function(a,b){
return a.id !== b.id;
}).reduce(function(last, item){
if(item.id === last.id){ theFunction(last.value1, item.value2) }
return item;
}, {});
function theFunction(value1, value2) {
var div = document.getElementById('out');
div.innerHTML += '<br />value1: ' + value1 + ', value2: ' + value2;
}
<div id='out'>
</div>
我认为这是一样的,但是一个更优雅的解决方案:
arr1.forEach(function(e,i) {
var same = arr2.filter(function(o, p) {
var eq = o.id === e.id;
if(eq) { arr2.splice(p, 1); } // remove used elements
return eq;
});
// here 'same' is an array of objects with the same id,
// we don't know how big it is, but
// at least the first position always has something
if(same.length) {
console.log(e, ", ", same[0])
}
})
相关文章:
- jQuery匹配JSON对象的部分文本
- 如何在Javascript中将JSon对象转换为数组
- 我可以在json对象中添加一个函数吗
- 使用JS将数组转换为json对象
- 我应该如何将响应数据保存在对象(json)中以获得更好的操作和性能
- 用javascript从列表对象(JSON的)构建diffrent选项卡
- php请求带有多个对象json-jquery
- AngularJS,过滤器:如何将一个巨大的对象(JSON)变成一个数组
- 动态属性对象 - JSON
- JavaScript 对象 (JSON) 中的动态设置值
- 从数组查询获取对象 JSON 值时出错
- 使用jQuerygetJSON将多维对象JSON转换为HTML
- 需要从 Angular JS 应用程序中的另一个 JSON 对象数组填充 JSON 数组的每个对象 JSON 对象数组
- 嵌套对象JSON排序JavaScript
- PHP在MySQL中保存来自Javascript的对象"JSON.stringify"通过Ajax
- 将JavaScript对象/ JSON转换为PHP数组
- JSON对象.JSON对象内部
- 访问对象的对象- JSON API
- 数组到对象JSON
- Message":"传入的无效对象(JSON数据格式化问题)