3

I am trying to merge two arrays of objects together.

I have presorted the arrays of objects so that they match, I just need to push the properties across each object in both arrays.

I think lodash would give me a cleaner solution than a double for loop, or should I just do a vanilla JS solution?

Example of two arrays:

[
    {
        provider: 'foo',
        title: 'Title1'
    },
    {
        provider: 'bar',
        title: 'Title2'
    }
]

[
    {
        all: '0',
        novelty: '24'
    },
    {
        all: '4',
        novelty: '12'
    }
]

It should return:

[
    {
        provider: 'foo',
        title: 'Title1',
        all: '0',
        novelty: '24'
    },
    {
        provider: 'bar',
        title: 'Title2',
        all: '4',
        novelty: '12'
    }
]
Tulun
  • 469
  • 4
  • 15

3 Answers3

2

Without lodash you can use Array.prototype.map() and Object.assign() (or angular.merge() if assign is not supported by the target browsers):

var arr1 = [{
      provider: 'foo',
      title: 'Title1'
    }, {
      provider: 'bar',
      title: 'Title2'
    }];

    var arr2 = [{
      all: '0',
      novelty: '24'
    }, {
      all: '4',
      novelty: '12'
    }];

    var result = arr1.map(function(item, index) {
      return Object.assign({}, item, arr2[index]);
    });

    console.log(result);

If you want to use lodash use _.zipWith() with _.assign():

var arr1 = [{
  provider: 'foo',
  title: 'Title1'
}, {
  provider: 'bar',
  title: 'Title2'
}];

var arr2 = [{
  all: '0',
  novelty: '24'
}, {
  all: '4',
  novelty: '12'
}];

var result = _.zipWith(arr1, arr2, function(a, b) {
  return _.assign({}, a, b);
});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • This worked (no lodash). I think I'll see if I can figure out how to inject lodash into the project in case I might need it (this is an Angular project), but I have decided for now to move on since it's not entirely trivial. – Tulun Oct 29 '16 at 20:25
  • With the array methods like map, reduce, forEach, every, some, etc... and the utilities in angular, merge for example, you hardly need lodash. If you want to include lodash, you can do so as a global or wrap it in an angular service. – Ori Drori Oct 29 '16 at 20:27
2

You can do this with ES6:

data1.map( (obj, i) => Object.assign({}, obj, data2[i]) )

var data1 = [{
        provider: 'foo',
        title: 'Title1'
    }, {
        provider: 'bar',
        title: 'Title2'
    }];
var data2 = [{
        all: '0',
        novelty: '24'
    }, {
        all: '4',
        novelty: '12'
    }];

var merged = data1.map( (obj, i) => Object.assign({}, obj, data2[i]) );

console.log(merged);
trincot
  • 317,000
  • 35
  • 244
  • 286
1

So far the other answers to this question are sub-optimal in that they ignore your stated condition that the input arrays are pre-sorted. AFAIK lodash has no pre-built method for merging sorted arrays, but a Google search for "merge sorted arrays" will reveal lots of pseudocode to emulate.

For example, here's a JS implementation of http://www.algolist.net/Algorithms/Merge/Sorted_arrays:

const mergeSortedArraysBy = (array1, array2, iteratee) => {
    const mergedArray = [];
    let i = 0;
    let j = 0;
    while (i < array1.length && j < array2.length) {
        if (iteratee(array1[i]) <= iteratee(array2[j])) {
            mergedArray.push(array1[i]);
            i++;
        } else {
            mergedArray.push(array2[j]);
            j++;
        }
    }
    if (i < array1.length) {
        for (let p = i; p < array1.length; p++) {
            mergedArray.push(array1[p]);
        }
    } else {
        for (let p = j; p < array2.length; p++) {
            mergedArray.push(array2[p]);
        }
    }
    return mergedArray;
};
Emmett
  • 14,035
  • 12
  • 56
  • 81