2

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.

1
  • There is no "JSON array". You have an array literal that contains object literals. At runtime, they are just arrays of objects, the fact that they were declared using object literal syntax is irrelevant. Commented Jan 17, 2019 at 5:37

3 Answers 3

3

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

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

6 Comments

Can you kindly show me in JSFIddle/JSBin? The Run Code Snippet Functionality is not working
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
There will be 3 fields for all, your solution has 2 fields for some items
There should be 3 fields for all, in case one field/key is not present, I need to assign '' (blank string)
I upvoted your answer and marked it as correct. The other person answered me earlier but I upvoted you since your answer has lots of comments and is helping to understand.
|
0

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

3 Comments

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.
There will be 3 fields for all, your solution has 2 fields for some items
@tommy123 updated adding empty strings whey key is not defined =)
0

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

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.