How to use Lodash to merge two collections based on a key?

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

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?

回答1:

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);
 


回答2:

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) + '
');


回答3:

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(); 


回答4:

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); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!