tommy123
tommy123

Reputation: 587

How to merge the key-value pairs of two json arrays? - Javascript

I have two JSON arrays like this. I want to merge their keyvalue pairs. They are some items which are common in both while they are some items which are uncommon.

var jsonData1 = [
  {
    firstName: "Sam",
    age: "10"
  },
  {
    firstName: "John",
    age: "11"
  },
  {
    firstName: "Jack",
    age: "12"
  },
  {
    firstName: "Pam",
    age: "13"
  },
  {
    firstName: "Tom",
    age: "14"
  },
  {
    firstName: "Mitch",
    age: "15"
  }
];

var jsonData2 = [
      {
        firstName: "Sam",
        city: "London"
      },
      {
        firstName: "John",
        city: "New York"
      },
      {
        firstName: "Jack",
        city: "Paris"
      },
      {
        firstName: "Pam",
        city: "Moscow"
      },
      {
        firstName: "Roger",
        city: "Shanghai"
      },
      {
        firstName: "Don",
        city: "Jakarta"
      }
    ];

As you can there are some firstName in 1st array which does not have city in 2nd array. Again there are some firstName in 2nd array which does not have city in 1st array.

I need to club these 2 array into one array, in case a firstName does not have age or city it will be assigned '' (blank string).

The new array will have 3 fields, there are some items which will be having values in 2 fields. They have a one field as blank string.

I want to do this using Vanilla JS, I do not want to use Jquery, Lodash and Underscore.

Upvotes: 2

Views: 2563

Answers (3)

Tyler Roper
Tyler Roper

Reputation: 21672

I realize you've already accepted an answer but I figured I could provide an alternative, be it better or worse.

var jsonData1 = [{firstName: "Sam",age: "10"},{firstName: "John",age: "11"},{firstName: "Jack",age: "12"},{firstName: "Pam",age: "13"},{firstName: "Tom",age: "14"},{firstName: "Mitch",age: "15"}];
var jsonData2 = [{firstName: "Sam",city: "London"},{firstName: "John",city: "New York"},{firstName: "Jack",city: "Paris"},{firstName: "Pam",city: "Moscow"},{firstName: "Roger",city: "Shanghai"},{firstName: "Don",city: "Jakarta"}];

var defaults = {firstName: "", age: "", city: ""};
var data  = [ ...jsonData1, ...jsonData2 ];
var names = [ ...new Set(data.map(i=>i.firstName)) ];

var res = names.map(n => data
                  .reduce((acc, jd) => jd.firstName === n ? {...acc, ...jd} : acc, defaults)
                );

console.log(res);

var data combines the two arrays of data into one using spread syntax (array literals).

var names creates an array of unique names using Set.

map() iterates over the list of names, creating a single, merged object for each. That merge is done using reduce() and spread syntax (object literals).

Upvotes: 0

Dacre Denny
Dacre Denny

Reputation: 30390

There are a number of ways to approach this, however one option would be to base this around the Array#reduce() method as follows:

const jsonData1=[{firstName:"Sam",age:"10"},{firstName:"John",age:"11"},{firstName:"Jack",age:"12"},{firstName:"Pam",age:"13"},{firstName:"Tom",age:"14"},{firstName:"Mitch",age:"15"}];
const jsonData2=[{firstName:"Sam",city:"London"},{firstName:"John",city:"New York"},{firstName:"Jack",city:"Paris"},{firstName:"Pam",city:"Moscow"},{firstName:"Roger",city:"Shanghai"},{firstName:"Don",city:"Jakarta"}];


/* 
Use Array#concat() to combine both input arrays before performing
the merge. This will ensure that all items in both arrays are
processed and accounted for during the merge (which is important in
situations where the input arrays differ in length).

Object.values() is used to transform the dictionary resulting from
reduce() to an array
*/
var result = Object.values(
[].concat(jsonData1, jsonData2
).reduce((dict, item) => {

  /* 
  We use Array#reduce is an intermediate step to construct a dictionary
  which maps each unique "item.firstName" to a corresponding object 
  that contains the merged (or yet to be merged) data for this first 
  name
  */
   
  var value = dict[item.firstName] || {}

  /*
  Use Object.assign() to merge existing data for "item.firstName" with
  current item being processed. Also pass default values as first
  argument to ensure all three key values are present in merge result
  */
  value = Object.assign({ firstName : '', age : '', city : ''} , value, item)

  /*
  Update the dictionary with merged data
  */
  dict[item.firstName] = value

  return dict

}, {}))

console.log(result);

Upvotes: 3

guijob
guijob

Reputation: 4488

One possible approach:

const jsonData1=[{firstName:"Sam",age:"10"},{firstName:"John",age:"11"},{firstName:"Jack",age:"12"},{firstName:"Pam",age:"13"},{firstName:"Tom",age:"14"},{firstName:"Mitch",age:"15"}];
const jsonData2=[{firstName:"Sam",city:"London"},{firstName:"John",city:"New York"},{firstName:"Jack",city:"Paris"},{firstName:"Pam",city:"Moscow"},{firstName:"Roger",city:"Shanghai"},{firstName:"Don",city:"Jakarta"}];

const result = [].concat(jsonData1, jsonData2).reduce((acc, ele) => {
        const existing = acc.find(x => x.firstName === ele.firstName);
        if(!existing) return acc.concat({firstName: ele.firstName, city: ele.city || '', age: ele.age || ''});
        Object.keys(ele).forEach(x => existing[x] = ele[x]);
        return acc;
    },[])
    
console.log(result);

Upvotes: 0

Related Questions