Tulun
Tulun

Reputation: 469

Merge 2 sorted array of objects using lodash by their properties

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'
    }
]

Upvotes: 3

Views: 2866

Answers (3)

Emmett
Emmett

Reputation: 14337

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;
};

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 193358

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>

Upvotes: 2

trincot
trincot

Reputation: 351403

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);

Upvotes: 2

Related Questions