How can i merge array of objects with underscore j

2019-02-17 10:40发布

问题:

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.

回答1:

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.