Joining / expanding arrays of javascript objects based on combining the key property in each

I want to combine the following arrays of objects by first joining 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' }]; 

Thus, the result will 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 when I have a loop with an inner loop, if the keys match, it copies the properties and breaks out of the inner loop to start the next outer loop.

Any best deals?

+4
source share
2 answers

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 are the same length and the id are equal, a simpler merge is performed:

 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 is a working example

[ Edit 2016/07/30 ] A fragment was added using a more functional approach and, based on a comment by @djangos, an additional method for combining 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> 
+4
source

You can combine two arrays by id column with Alasql :

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

Try this example in jsFiddle .

+1
source

All Articles