1

I have two JSON arrays in Node.js.

var a = [{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 3, name: 'C'}, {id: 4, name: 'D'}];

var b = [{id: 1, marks: 80}, {id: 2, marks: 30}, {id: 3, marks: 76}];

I want to merge these arrays, matching the id values. Please suggest an efficient way to do this, because arrays contain around 25000 records.

Desired Output:

var o = [{id: 1, name: 'A', marks: 80}, {id: 2, name: 'B', marks: 30}, {id: 3, name: 'C', marks: 76}, {id: 4, name: 'D'}];

Thanks.

Rahul Patel
  • 639
  • 6
  • 12
  • Have a look at this question: [JavaScript merging objects by id](http://stackoverflow.com/questions/19480008/javascript-merging-objects-by-id) – Gruff Bunny Oct 04 '16 at 08:57

3 Answers3

4

You should make an index object

const indexB = b.reduce( ( result, item ) => { 
    result[item.id] = item; 
    return result; 
}, {});

var mergedArr = a.map( item => Object.assign( item, indexB[item.id] ) );

In my benchmark the underscore method and my method had a significant difference :

λ ~/Projects/_tests/performance ◆ time node a.js
node a.js  44.36s user 0.38s system 98% cpu 45.216 total
λ ~/Projects/_tests/performance ◆ time node b.js
node b.js  0.10s user 0.02s system 95% cpu 0.118 total

Where a.js is with underscore.

drinchev
  • 19,201
  • 4
  • 67
  • 93
  • 1
    If you use `Object.assign` (ES6), you should probably use a `Map` rather than an object for the index as well? – jcaron Oct 04 '16 at 08:58
1

Using underscore, you could do something like this:

var mergedArr = _.map(v1, function(item){
    return _.extend(item, _.findWhere(v2, { id: item.id }));
});
James111
  • 15,378
  • 15
  • 78
  • 121
1

Or something like this:

a.map(function (aObj) {
  aObj.marks = (b.filter(function (bObj) {
    return bObj.id === aObj.id;
  }).shift() || {
    marks: null
  }).marks;
});

console.log(a);

// output: 
[ { id: 1, name: 'A', marks: 80 },
  { id: 2, name: 'B', marks: 30 },
  { id: 3, name: 'C', marks: 76 },
  { id: 4, name: 'D', marks: null } ]
Bas van Ommen
  • 1,243
  • 2
  • 12
  • 20