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.
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.