Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge two arrays of objects by ID using lodash? [duplicate]

I have two array with one common field member. how can I merge theme easily?

For example:

var arr1 = [{   "member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),   "bank" : ObjectId("575b052ca6f66a5732749ecc"),   "country" : ObjectId("575b0523a6f66a5732749ecb") }, {   "member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),   "bank" : ObjectId("575b052ca6f66a5732749ecc"),   "country" : ObjectId("575b0523a6f66a5732749ecb") }];  var arr2 = [{     "member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),     "name" : 'xxxxxx',     "age" : 25 }, {     "member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),     "name" : 'yyyyyyyyyy',     "age" : 26 }]; 

Expected:

var merge = [{   "member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),   "bank" : ObjectId("575b052ca6f66a5732749ecc"),   "country" : ObjectId("575b0523a6f66a5732749ecb"),   "name" : 'xxxxxx',   "age" : 25 }, {   "member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),   "bank" : ObjectId("575b052ca6f66a5732749ecc"),   "country" : ObjectId("575b0523a6f66a5732749ecb"),   "name" : 'yyyyyyyyyy',   "age" : 26 }]; 

I tried

var merge = _.unionBy(arr1, arr2, 'member'); 

but not merged as expected. shown array1 value. can any one help me?

like image 423
Shaishab Roy Avatar asked Jul 27 '16 12:07

Shaishab Roy


People also ask

How do I merge two arrays in Lodash?

concat() function is used to concatenating the arrays in JavaScript. Parameters: This function accept two parameters as mentioned above and described below: array: It is an array to which values are to be added.

How do you merge an array of objects into a single object?

Use the Array. We can use the JavaScript array reduce method to combine objects in an array into one object. We have the arr array which we want to combine into one object. To do that, we call reduce with a callback that returns an object with obj spread into the returned object. And we add the item.


2 Answers

If both arrays are in the correct order; where each item corresponds to its associated member identifier then you can simply use.

var merge = _.merge(arr1, arr2); 

Which is the short version of:

var merge = _.chain(arr1).zip(arr2).map(function(item) {     return _.merge.apply(null, item); }).value(); 

Or, if the data in the arrays is not in any particular order, you can look up the associated item by the member value.

var merge = _.map(arr1, function(item) {     return _.merge(item, _.find(arr2, { 'member' : item.member })); }); 

You can easily convert this to a mixin. See the example below:

_.mixin({    'mergeByKey' : function(arr1, arr2, key) {      var criteria = {};      criteria[key] = null;      return _.map(arr1, function(item) {        criteria[key] = item[key];        return _.merge(item, _.find(arr2, criteria));      });    }  });    var arr1 = [{    "member": 'ObjectId("57989cbe54cf5d2ce83ff9d6")',    "bank": 'ObjectId("575b052ca6f66a5732749ecc")',    "country": 'ObjectId("575b0523a6f66a5732749ecb")'  }, {    "member": 'ObjectId("57989cbe54cf5d2ce83ff9d8")',    "bank": 'ObjectId("575b052ca6f66a5732749ecc")',    "country": 'ObjectId("575b0523a6f66a5732749ecb")'  }];    var arr2 = [{    "member": 'ObjectId("57989cbe54cf5d2ce83ff9d8")',    "name": 'yyyyyyyyyy',    "age": 26  }, {    "member": 'ObjectId("57989cbe54cf5d2ce83ff9d6")',    "name": 'xxxxxx',    "age": 25  }];    var arr3 = _.mergeByKey(arr1, arr2, 'member');    document.body.innerHTML = JSON.stringify(arr3, null, 4);
body { font-family: monospace; white-space: pre; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>
like image 150
Mr. Polywhirl Avatar answered Sep 21 '22 18:09

Mr. Polywhirl


Create dictionaries for both arrays using _.keyBy(), merge the dictionaries, and convert the result to an array with _.values(). In this way, the order of the arrays doesn't matter. In addition, it can also handle arrays of different length.

const ObjectId = (id) => id; // mock of ObjectId  const arr1 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")}];  const arr2 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"name" : 'xxxxxx',"age" : 25},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"name" : 'yyyyyyyyyy',"age" : 26}];    const merged = _(arr1) // start sequence    .keyBy('member') // create a dictionary of the 1st array    .merge(_.keyBy(arr2, 'member')) // create a dictionary of the 2nd array, and merge it to the 1st    .values() // turn the combined dictionary to array    .value(); // get the value (array) out of the sequence    console.log(merged);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>

Using ES6 Map

Concat the arrays, and reduce the combined array to a Map. Use Object#assign to combine objects with the same member to a new object, and store in map. Convert the map to an array with Map#values and spread:

const ObjectId = (id) => id; // mock of ObjectId  const arr1 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"bank" : ObjectId("575b052ca6f66a5732749ecc"),"country" : ObjectId("575b0523a6f66a5732749ecb")}];  const arr2 = [{"member" : ObjectId("57989cbe54cf5d2ce83ff9d6"),"name" : 'xxxxxx',"age" : 25},{"member" : ObjectId("57989cbe54cf5d2ce83ff9d8"),"name" : 'yyyyyyyyyy',"age" : 26}];    const merged = [...arr1.concat(arr2).reduce((m, o) =>     m.set(o.member, Object.assign(m.get(o.member) || {}, o))  , new Map()).values()];    console.log(merged);
like image 29
Ori Drori Avatar answered Sep 20 '22 18:09

Ori Drori