使用下划线组合两个对象数组
Combine two arrays of objects using underscore
我有两个对象数组:
var a = [{id:456, name:'sojuz'},
{id:751, name:'sputnik'},
{id:56, name:'arianne'}]
var b = [{id:751, weight:5800},
{id:456, weight:2659},
{id:56, weight:6700}]
使用 underscorejs 如何将数组 a 扩展到新数组 c 添加权重 属性 来自数组 b 其中 id 属性 相同:
var c = [{id:456, name:'sojuz', weight:2659},
{id:751, name:'sputnik', weight:5800},
{id:56, name:'arianne', weight:6700}]
类似这样的方法可以工作,但绝对不是最佳选择:
var c = [];
for(var i = 0; i < a.length; i++) {
for (var j = 0; j < b.length; j++) {
if(b[j].id == a[i].id) {
var newC = {
id: a[i].id,
name: a[i].name,
weight: b[j].weight
}
c.push(newC);
break;
}
}
}
但是,这确实有 O(n^2) 的复杂度,我相信它可以被优化。
这是使用下划线的一种方法:
var c = _.map(a, function(element) {
var treasure = _.findWhere(b, { id: element.id });
return _.extend(element, treasure);
});
如果你想fiddle(看看我在那里做了什么):http://jsfiddle.net/b90pyxjq/3/
您可以将列表 a
和列表 b
中的每个索引 (_.indexBy
) 对象映射 (_.map
) 到扩展对象 (_.extend
) 生成合并对象列表。
以下解决方案利用了 Underscore.js 库。
var a = [
{ id: 456, name: 'sojuz' },
{ id: 751, name: 'sputnik' },
{ id: 56, name: 'arianne' }
];
var b = [
{ id: 751, weight: 5800 },
{ id: 456, weight: 2659 },
{ id: 56, weight: 6700 }
];
function mergeLists(listA, listB, idField) {
var indexA = _.indexBy(a, idField)
var indexB = _.indexBy(b, idField);
return _.map(indexA, function(obj, key) {
return _.extend(obj, indexB[key]);
});
}
var c = mergeLists(a, b, 'id');
document.body.innerHTML = JSON.stringify(c, null, ' ');
body {
white-space: pre;
font-family: monospace;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
编辑
我修改了上面的原始示例,删除了 a
列表中不必要的索引。我的解决方案比上面的 运行效率更高,大约快 48%。
您可以在此处查看实际效果:http://jsperf.com/underscore-merge/3
function mergeLists3(listA, listB, idField) {
var indexB = _.indexBy(listB, idField);
return _.map(listA, function(obj, key) {
return _.extend(obj, indexB[obj[idField]]);
});
}
使用 ES6 或使用带有 polyfill 替换的 ES5 复制任何 属性 不带下划线的名称:
a.map(function (aItem) {
var found = b.find(function (bItem) {
if (aItem.id == bItem.id) return true;
}) || {};
Object.getOwnPropertyNames(found).map (function (property) {
aItem[property] = found[property];
});
});
我有两个对象数组:
var a = [{id:456, name:'sojuz'},
{id:751, name:'sputnik'},
{id:56, name:'arianne'}]
var b = [{id:751, weight:5800},
{id:456, weight:2659},
{id:56, weight:6700}]
使用 underscorejs 如何将数组 a 扩展到新数组 c 添加权重 属性 来自数组 b 其中 id 属性 相同:
var c = [{id:456, name:'sojuz', weight:2659},
{id:751, name:'sputnik', weight:5800},
{id:56, name:'arianne', weight:6700}]
类似这样的方法可以工作,但绝对不是最佳选择:
var c = [];
for(var i = 0; i < a.length; i++) {
for (var j = 0; j < b.length; j++) {
if(b[j].id == a[i].id) {
var newC = {
id: a[i].id,
name: a[i].name,
weight: b[j].weight
}
c.push(newC);
break;
}
}
}
但是,这确实有 O(n^2) 的复杂度,我相信它可以被优化。
这是使用下划线的一种方法:
var c = _.map(a, function(element) {
var treasure = _.findWhere(b, { id: element.id });
return _.extend(element, treasure);
});
如果你想fiddle(看看我在那里做了什么):http://jsfiddle.net/b90pyxjq/3/
您可以将列表 a
和列表 b
中的每个索引 (_.indexBy
) 对象映射 (_.map
) 到扩展对象 (_.extend
) 生成合并对象列表。
以下解决方案利用了 Underscore.js 库。
var a = [
{ id: 456, name: 'sojuz' },
{ id: 751, name: 'sputnik' },
{ id: 56, name: 'arianne' }
];
var b = [
{ id: 751, weight: 5800 },
{ id: 456, weight: 2659 },
{ id: 56, weight: 6700 }
];
function mergeLists(listA, listB, idField) {
var indexA = _.indexBy(a, idField)
var indexB = _.indexBy(b, idField);
return _.map(indexA, function(obj, key) {
return _.extend(obj, indexB[key]);
});
}
var c = mergeLists(a, b, 'id');
document.body.innerHTML = JSON.stringify(c, null, ' ');
body {
white-space: pre;
font-family: monospace;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
编辑
我修改了上面的原始示例,删除了 a
列表中不必要的索引。我的解决方案比上面的
您可以在此处查看实际效果:http://jsperf.com/underscore-merge/3
function mergeLists3(listA, listB, idField) {
var indexB = _.indexBy(listB, idField);
return _.map(listA, function(obj, key) {
return _.extend(obj, indexB[obj[idField]]);
});
}
使用 ES6 或使用带有 polyfill 替换的 ES5 复制任何 属性 不带下划线的名称:
a.map(function (aItem) {
var found = b.find(function (bItem) {
if (aItem.id == bItem.id) return true;
}) || {};
Object.getOwnPropertyNames(found).map (function (property) {
aItem[property] = found[property];
});
});