1

I have 2 arrays of objects:

var a = [
    { "image_id": 631293, "score": 73 }, 
    { "image_id": 11848407, "score": 56 }
];

var b = [
    { "image_id": 631293, "article_id": 173 }, 
    { "image_id": 11848407, "article_id": 121 }
];

I have tried to apply method described in How can i merge array of objects with underscore js but unfortunately it does not work at all.

My need is to merge both arrays of objects thanks to image_id.

So I tried this :

_.values(
   _.extendOwn(
      _.indexBy(a, 'image_id'),
      _.indexBy(b, 'image_id')
   )
)

but output just return me this array of object a

I need to get :

[
    {"image_id": 631293, "score": 73, "article_id": 173}, 
    {"image_id": 11848407, "score": 56, "article_id": 121}
]

How can I achieve this without doing a loop to check every element of array and use a findWhere?

0

2 Answers 2

3

Using indexBy is a good start. Then loop and extend one:

var indexed = _.indexBy(a, 'image_id');

_.each(b, function(obj) {
  var master = indexed[obj.image_id];
  if (master) _.extend(master, obj);
});

or if you want a new array and let the original objects untouched:

var result = _.map(b, function(obj) {
  var master = indexed[obj.image_id];
  return _.extend({}, master, obj);
});

var a = [{
  "image_id": 11848407,
  "score": 56
}, {
  "image_id": 631293,
  "score": 73
}, {
  "image_id": "dummy",
  "score": 1
}];

var b = [{
  "image_id": "test",
  "article_id": 0
}, {
  "image_id": 631293,
  "article_id": 173
}, {
  "image_id": 11848407,
  "article_id": 121
}];

var indexed = _.indexBy(a, 'image_id');

_.each(b, function(obj) {
  var master = indexed[obj.image_id];
  if (master) _.extend(master, obj);
});

console.log(a);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Sign up to request clarification or add additional context in comments.

1 Comment

Great solution!
1

You can use _.zip as follows:

var a = [
  { "image_id": 631293, "score": 73 }, 
  { "image_id": 11848407, "score": 56 }
];

var b = [
  { "image_id": 631293, "article_id": 173 }, 
  { "image_id": 11848407, "article_id": 121 }
];

var c = _.zip(a, b).map(function(elem){
  return _.extendOwn(elem[0], elem[1]);
});

4 Comments

Thanks for this great tip!
@Toucouleur This doesn't work if they're not ordered as it doesn't take the image_id into account.
This will work only if the source arrays happen to be sorted and a one for one match. Basically, this is not your solution.
Agreed with the commenters. This WILL work for THIS question, but only because the array elements in both arrays are matching up, which is a great use case for the _.zip as described in documentation underscorejs.org/#zip

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.