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

murvinlai picture murvinlai · Jan 29, 2016 · Viewed 45.4k times · Source

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?

Answer

Tushar picture Tushar · Jan 29, 2016

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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.1.0/lodash.min.js"></script>
<pre id="result"></pre>