[英]How to use Lodash to merge two collections based on a key?
我有兩個集合,對象有一個公共鍵“userId”。 如下:
var _= require('lodash');
var a = [
{ userId:"p1", item:1},
{ userId:"p2", item:2},
{ userId:"p3", item:4}
];
var b = [
{ userId:"p1", profile:1},
{ userId:"p2", profile:2}
];
我想根據“userId”合並它們以產生:
[ { userId: 'p1', item: 1, profile: 1 },
{ userId: 'p2', item: 2, profile:2 },
{ userId: 'p3', item: 4 } ]
到目前為止,我有這些:
var u = _.uniq(_.union(a, b), false, _.property('userId'));
結果是:
[ { userId: 'p1', item: 1 },
{ userId: 'p2', item: 2 },
{ userId: 'p3', item: 4 },
{ userId: 'p1', profile: 1 },
{ userId: 'p2', profile: 2 } ]
我現在如何合並它們?
我試過 _.keyBy 但結果是:
{ p1: { userId: 'p1', profile: 1 },
p2: { userId: 'p2', profile: 2 },
p3: { userId: 'p3', item: 4 } }
這是錯誤的。
我應該做的最后一步是什么?
投票第二高的答案沒有正確合並。 如果第二個數組包含唯一屬性,則不考慮。
這種方法進行了適當的合並。
var a = [ { userId:"p1", item:1}, { userId:"p2", item:2}, { userId:"p3", item:4} ]; var b = [ { userId:"p1", profile:1}, { userId:"p2", profile:2}, { userId:"p4", profile:4} ]; var merged = _.merge(_.keyBy(a, 'userId'), _.keyBy(b, 'userId')); var values = _.values(merged); console.log(values);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
// from https://stackoverflow.com/a/34749873/80766 const mergeDeep = (target, ...sources) => { if (!sources.length) return target; const source = sources.shift(); if (target instanceof Object && source instanceof Object) { for (const key in source) { if (source[key] instanceof Object) { if (!target[key]) Object.assign(target, { [key]: {} }); mergeDeep(target[key], source[key]); } else { Object.assign(target, { [key]: source[key] }); } } } return mergeDeep(target, ...sources); } const a = [ { userId:"p1", item:1}, { userId:"p2", item:2}, { userId:"p3", item:4} ]; const b = [ { userId:"p1", profile:1}, { userId:"p2", profile:2}, { userId:"p4", profile:4} ]; const aKeyed = a.reduce((acc, cur) => ({ ...acc, [cur.userId]: cur }), {}); const bKeyed = b.reduce((acc, cur) => ({ ...acc, [cur.userId]: cur }), {}); const merged = mergeDeep(aKeyed, bKeyed); const values = Object.values(merged); console.log(values);
您可以使用_.map()
、 _.assign()
和_.find()
。
// Iterate over first array of objects
_.map(a, function(obj) {
// add the properties from second array matching the userID
// to the object from first array and return the updated object
return _.assign(obj, _.find(b, {userId: obj.userId}));
});
var a = [{ userId: "p1", item: 1 }, { userId: "p2", item: 2 }, { userId: "p3", item: 4 }]; var b = [{ userId: "p1", profile: 1 }, { userId: "p2", profile: 2 }]; var arrResult = _.map(a, function(obj) { return _.assign(obj, _.find(b, { userId: obj.userId })); }); console.log(arrResult); document.getElementById('result').innerHTML = JSON.stringify(arrResult, 0, 4);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.1.0/lodash.min.js"></script> <pre id="result"></pre>
Lodash 有一個適用於對象的merge
方法(合並具有相同鍵的對象)。 在這個演示中,數組a
和b
首先轉換為對象(其中userId
是鍵),然后合並,並將結果轉換回數組( _.values
)(去掉鍵)。 _.flatten
然后是必要的,因為_.values
增加了一個額外的數組級別。
var u= _({}) // Start with an empty object
.merge(
_(a).groupBy("userId").value(),
_(b).groupBy("userId").value()
)
.values()
.flatten()
.value();
只是為了完整性:一個沒有任何圖書館的提案。
function merge(a, b, key) { function x(a) { a.forEach(function (b) { if (!(b[key] in obj)) { obj[b[key]] = obj[b[key]] || {}; array.push(obj[b[key]]); } Object.keys(b).forEach(function (k) { obj[b[key]][k] = b[k]; }); }); } var array = [], obj = {}; x(a); x(b); return array; } var a = [ { userId: "p1", item: 1 }, { userId: "p2", item: 2 }, { userId: "p3", item: 4 } ], b = [ { userId: "p1", profile: 1 }, { userId: "p2", profile: 2 } ], c = merge(a, b, 'userId'); document.write('<pre>' + JSON.stringify(c, 0, 4) + '</pre>');
沒有 lodash 的 ES6+ 版本。
const array1 = [{ userId: "p1", item: 1 }, { userId: "p2", item: 2 },{ userId: "p3", item: 4 }]; const array2 = [{ userId: "p1", profile: 1 }, { userId: "p2", profile: 2 }]; const result = array1.map(a => ({ ...a, ...array2.find(b => b.userId === a.userId) // _.find(array2, 'skuId') <-- or with lodash })); document.write('<pre>' + JSON.stringify(result, 0, 2) + '</pre>');
試試這個演示
var a = [{
userId: "p1",
item: 1
}, {
userId: "p2",
item: 2
}, {
userId: "p3",
item: 4
}];
var b = [{
userId: "p1",
profile: 1
}, {
userId: "p2",
profile: 2
}];
a.forEach(function (aitem) {
b.forEach(function (bitem) {
if(aitem.userId === bitem.userId) {
_.assign(aitem, bitem);
}
});
});
console.log(a);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.