4

I am wanting to merge the following object arrays, by first joining on the id property

var arr1 = [{
    id: 1,
    name: 'fred',
    title: 'boss'
},{
    id: 2,
    name: 'jim',
    title: 'nobody'
},{
    id: 3,
    name: 'bob',
    title: 'dancer'
}];

var arr2 = [{
    id: 1,
    wage: '300',
    rate: 'day'
},{
    id: 2,
    wage: '10',
    rate: 'hour'
},{
    id: 3,
    wage: '500',
    rate: 'week'
}];

So the result would be

[{
    id: 1,
    name: 'fred',
    title: 'boss',
    wage: '300',
    rate: 'day'
},{
    id: 2,
    name: 'jim',
    title: 'nobody',
    wage: '10',
    rate: 'hour'
},{
    id: 3,
    name: 'bob',
    title: 'dancer',
    wage: '500',
    rate: 'week'
}]

I would like to avoid using js frameworks (if possible), although ExtJs is already part of the project. AT the moment I have a loop with an inner loop that if the keys match it copies the properties and breaks out of the inner loop to start the next outer loop.

Any better suggestions?

1
  • This would be relatively easy to do with jQuery with the help of .extend -- anyhow, can you show the code you have so far, and does it work? Are you looking for an optimized solution? Commented May 19, 2011 at 13:30

3 Answers 3

4

Like this?

var combined = [];
function findSecond(id,second){
    for (var i=0;i<second.length;i++){
        if(second[i].id === id){
            return second[i];
        }
    }
    return null
}

while (el = arr1.pop()){
    var getSec = findSecond(el.id,arr2);
    if (getSec){
        for (var l in getSec){
            if (!(l in el)) {
                el[l] = getSec[l];
            }
        }
        combined.push(el);
    }
}

If the arrays have the same length, and the id's are equal, a simpler merge will do:

function merge(a1,a2) {
    var i = -1;
    while ((i = i+1)<a1.length)  {
     for (var l in a2[i]) {
            if (!(l in a1[i] )) {
                a1[i][l] = a2[i][l];
            }
     }
    }
   return a1; 
}

Here's a working example

[Edit 2016/07/30] Added a snippet using more functional approach and, based on @djangos comment, an extra method to combine both arrays.

(function() {
    var alert = function(str) {document.querySelector('#result').textContent += str + '\n';};
    var arrays = getArrays();
  
    alert('Combine on id (shared id\'s):')
    alert(JSON.stringify(combineById(arrays.arr1, arrays.arr2), null, ' '));
  
    alert('\nCombine on id (all id\'s):')
    alert(JSON.stringify(combineBothById(arrays.arr1, arrays.arr2), null, ' '));
  
    // for combineBothById the parameter order isn't relevant
    alert('\nCombine on id (all id\'s, demo parameter order not relevant):')
    alert(JSON.stringify(combineBothById(arrays.arr2, arrays.arr1), null, ' '));
  
    // combine first array with second on common id's
    function combineById(arr1, arr2) {
      return arr1.map(
          function (el) {
                var findInB = this.filter(function (x) {return x.id === el.id;});
                if (findInB.length) {
                    var current = findInB[0];
                    for (var l in current) {
                        if (!el[l]) {el[l] = current[l];}
                    }
                }
                return el;
          }, arr2);
    }

    // combine first array with second on all id's
    function combineBothById(arr1, arr2) {
        var combined = arr1.map(
            function (el) {
                var findInB = this.filter(function (x) {return x.id === el.id;});
                if (findInB.length) {
                    var current = findInB[0];
                    for (var l in current) {
                        if (!el[l]) {el[l] = current[l];}
                    }
                }
                return el;
            }, arr2);
        combined = combined.concat(arr2.filter(
            function (el) {
                return !this.filter(function (x) {return x.id === el.id;}).length;
            }, combined));
        return combined;
    }
  
    function getArrays() {
        return {
            arr1: [{
                id: 1,
                name: 'fred',
                title: 'boss'
            }, {
                id: 2,
                name: 'jim',
                title: 'nobody'
            }, {
                id: 3,
                name: 'bob',
                title: 'dancer'
            }],
            arr2: [{
                id: 1,
                wage: '300',
                rate: 'day'
            }, {
                id: 2,
                wage: '10',
                rate: 'hour'
            }, {
                id: 4,
                wage: '500',
                rate: 'week'
            }]
        };
    }
}());
<pre id="result"></pre>

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

3 Comments

I was lookign for same thing but a bit different , please check jsfiddle.net/ZaJ4x/35 . I am expecting result to have ids 1,2,3,4
You seem to be wanting to combine from both array. Maybe this fiddle offers a solution: jsfiddle.net/7aobwxvv
@django added a snippet to the answer too
2

You can merge two arrays by id column with Alasql library:

var res = alasql('SELECT * FROM ? arr1 JOIN ? arr2 USING id', [arr1,arr2]);

Try this example at jsFiddle.

Comments

0

try this...

var arr1 = [{
    id: 1,
    name: 'fred',
    title: 'boss'
},{
    id: 2,
    name: 'jim',
    title: 'nobody'
},{
    id: 3,
    name: 'bob',
    title: 'dancer'
}];

var arr2 = [{
    id: 1,
    wage: '300',
    rate: 'day'
},{
    id: 2,
    wage: '10',
    rate: 'hour'
},{
    id: 3,
    wage: '500',
    rate: 'week'
}];

let arr5 = arr1.map((item, i) => Object.assign({}, item, arr2[i]));
console.log(arr5)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.