I have two collections, and the objects have a common key "userId". As below:
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} ];
I want to merge them based on "userId" to produce:
[ { userId: 'p1', item: 1, profile: 1 }, { userId: 'p2', item: 2, profile:2 }, { userId: 'p3', item: 4 } ]
I have these so far:
var u = _.uniq(_.union(a, b), false, _.property('userId'));
Which result in:
[ { userId: 'p1', item: 1 }, { userId: 'p2', item: 2 }, { userId: 'p3', item: 4 }, { userId: 'p1', profile: 1 }, { userId: 'p2', profile: 2 } ]
How can I merge them now?
I tried _.keyBy but it results in:
{ p1: { userId: 'p1', profile: 1 }, p2: { userId: 'p2', profile: 2 }, p3: { userId: 'p3', item: 4 } }
which is wrong.
What's the last step I should do?
You can use _.map(), _.assign() and _.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})); });
Fiddle Demo
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);
Just for completeness: A proposal without any library.
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('' + JSON.stringify(c, 0, 4) + '
');
Lodash has a merge method that works on objects (objects with the same key are merged). In this demo, the arrays a and b are first converted into objects (where userId is the key), then merged, and the result converted back to an array (_.values) (getting rid of the keys). _.flatten is then necessary because _.values adds an extra level of array.
var u= _({}) // Start with an empty object .merge( _(a).groupBy("userId").value(), _(b).groupBy("userId").value() ) .values() .flatten() .value();
Try this demo
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);