Combine json arrays by key, javascript

44,210

Solution 1

If you wanted to write it so that you could take in any number of arrays, not just 2, you could utilize arguments, and do something like this:

var json1 = [{id:1,name:'aaa'},{id:5,name:'ccc'},{id:3,name:'bbb'}];

var json2 = [{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
             {id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
             {id:5,parameter1:'q', parameter2:'w', parameter3:'e'}];

function joinObjects() {
  var idMap = {};
  // Iterate over arguments
  for(var i = 0; i < arguments.length; i++) {
    // Iterate over individual argument arrays (aka json1, json2)
    for(var j = 0; j < arguments[i].length; j++) {
      var currentID = arguments[i][j]['id'];
      if(!idMap[currentID]) {
        idMap[currentID] = {};
      }
      // Iterate over properties of objects in arrays (aka id, name, etc.)
      for(key in arguments[i][j]) {
        idMap[currentID][key] = arguments[i][j][key];
      }
    }
  }
  
  // push properties of idMap into an array
  var newArray = [];
  for(property in idMap) {
    newArray.push(idMap[property]);
  }
  return newArray;
}

var json3 = joinObjects(json1, json2);

console.log(JSON.stringify(json3));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Here is a working codepen.

Solution 2

Two one-liners:

with lodash:

res = _(json1).concat(json2).groupBy('id').map(_.spread(_.assign)).value();

in ES2015:

res = json2.map(x => Object.assign(x, json1.find(y => y.id == x.id)));

Solution 3

ES2015 georg's answer works great;

    json1 = [
    {id:1, test: 0},
    {id:2, test: 0},
    {id:3, test: 0},
    {id:4, test: 0},
    {id:5, test: 0}
];

json2 = [
    {id:1, test: 1},
    {id:3, test: 1},
    {id:5, test: 1}
];

json1.map(x => Object.assign(x, json2.find(y => y.id == x.id)));

result:

{id:1, test: 1},
{id:2, test: 0},
{id:3, test: 1},
{id:4, test: 0},
{id:5, test: 1}

Solution 4

let json1 = [
  { id: 1, name: 'aaa' },
  { id: 5, name: 'ccc' },
  { id: 3, name: 'bbb' }
];

let json2 = [
  { id: 3, parameter1: 'x', parameter2: 'y', parameter3: 'z' },
  { id: 1, parameter1: 'u', parameter2: 'v', parameter3: 'w' },
  { id: 5, parameter1: 'q', parameter2: 'w', parameter3: 'e' }
];

let result = json1.map(obj => {
  let data = json2.find(item => item.id === obj.id);
  return {...obj, ...data}
});

console.log(result);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Solution 5

Use nested loops to find the corresponding elements and merge them.

for (var i = 0; i < json1.length; i++) {
    var id = json1[i].id;
    for (var j = 0; j < json2.length; j++) {
        if (json2[j].id == id) {
            for (var key in json2[j]) {
                json1[i][key] = json2[j][key];
            }
            break;
        }
    }
}

At the end, json1 will contain the combined elements.

The above code assumes that every element of json2 matches something in json1. If there can be extra elements in json2, you'll need an additional loop afterward to copy those over to json1.

Share:
44,210
user2083142
Author by

user2083142

Updated on July 16, 2022

Comments

  • user2083142
    user2083142 almost 2 years

    I need to combine two json arrays, delivered by two rest services. The entries with the same "id" belong together.

    json1 = [{id:1,name:'aaa'},
         {id:5,name:'ccc'},
         {id:3,name:'bbb'}
       ];
    
     json2 = [{id:3,parameter1:'x', parameter2:'y', parameter3:'z'},
         {id:1,parameter1:'u', parameter2:'v', parameter3:'w'},
         {id:5,parameter1:'q', parameter2:'w', parameter3:'e'}
        ];
    

    I need a combined/copied/cloned json array in javascript in the following way (my model in angular2):

    json3 = [{id:3,name:'bbb',parameter1:'x', parameter2:'y',   parameter3:'z'},
         {id:1,name:'aaa', parameter1:'u', parameter2:'v', parameter3:'w'},
         {id:5,name:'ccc', parameter1:'q', parameter2:'w', parameter3:'e'}
        ];
    

    Is there a way to combine them? The parameter names are not defined exactly and it needs to work with variable parameter vectors.

    I tried it with mixed for each loops. Seems to me very ugly.