6

I have an array of objects like this:

array1 = [
  {field: 'username', display: 'username', hide: true},
  {field: 'age', display: 'Age', hide: true},
  {field: 'height', display: 'Height', hide: true}
]

Then I have array2:

array2 = [
  {field: 'username', display: 'username 123', hide: false},
  {field: 'age', hide: false}
]

I want to merge these two arrays by their field i.e. the final result should be:

array3 = [
  {field: 'username', display: 'username 123', hide: false},
  {field: 'age', display: 'Age', hide: false},
  {field: 'height', display: 'Height', hide: true}
]

I tried var newObj = _.extend(array1, array2); but it didn't give me what I want.

4
  • You are looking for concat. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Dec 18, 2014 at 22:24
  • @Brian: nope, he's doing some sort of updating. Commented Dec 18, 2014 at 22:25
  • @Karoly Horvath Ah yes, he wants to merge the objects as well as the array Commented Dec 18, 2014 at 22:26
  • it's not even clear what the order will be if array2 contains new elements... is the order important? if not, go with a plain object (as a dictionary). if it does, an order dictionary would be better for the task. it helps with the lookups. Commented Dec 18, 2014 at 22:27

1 Answer 1

11

There's no one function that will do it, as its a fairly specialized operation. However, its a fairly simple composition of underscore functions:

_.values(_.extend(_.indexBy(array1, 'field'), _.indexBy(array2, 'field')))

We use indexBy to turn the arrays into objects keyed on the field value, and then extend does what we want. Finally, values turns it back into an array.

Note that while this doesn't make any guarantees about the order, in the current _ and v8 implementations the final array will be the things from array1 followed by the things from array2 that aren't in array1, sorted in the original ordering of each array.

Also note that the _.extend function is destructive on the first argument, while this doesn't change either array.

If you want to be sure that the order is the same as the original array1:

order = _.object(_.map(array1, function(obj, i) { return [obj.field, i]; }))
_.sortBy(_.values(_.extend(_.indexBy(array1, 'field'), _.indexBy(array2, 'field'))), function(obj) { order[obj.field]; })

Here we make a lookup table of positions and then sort the original solution based on the lookup table.

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

4 Comments

thanks , that was what i want. How can i preserve the order . i mean i want that order should stay as of in first array. second array won't have any new elements. its only for updating
I have 2 list one is : [{"image_id": 631293, "score": 73}, {"image_id": 11848407, "score": 56}] second one is [{"image_id": 631293, "article_id": 173}, {"image_id": 11848407, "article_id": 121} if I try to apply your method, it does not change anything
@Toucouleur You probably want to replace 'field' with 'image_id', since it looks like that is your key field.
I am almost 3 years late but this answer is exactly what I am looking for. Thank you so much! :)

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.