Computer >> Computer tutorials >  >> Programming >> Javascript

Merging subarrays in JavaScript


Suppose, we have an array of arrays that contains information about the name and email of some people like this −

const arr = [
   ["John", "[email protected]", "[email protected]"],
   ["John", "[email protected]"],
   ["John", "[email protected]", "[email protected]"],
   ["Mary", "[email protected]"]
];

Each element of the array is a subarray of strings, where the first element is a name, and the rest of the elements are emails belonging to that name.

Now, we would like to merge these subarrays. Two subarrays definitely belong to the same person if there is some email that is common to both subarrays.

Note that even if two subarrays have the same name, they may belong to different people as people could have the same name.

A person can have any number of accounts initially, but all of their accounts definitely have the same name.

After merging the subarrays, we need to return them in the following format − the first element of each subarray is the name, and the rest of the elements are emails in sorted order. The subarrays themselves can be returned in any order.

Therefore, for the above array, the output should look like −

const output = [
   ["John", '[email protected]', '[email protected]',
   '[email protected]'],
   ["John", "[email protected]"],
   ["Mary", "[email protected]"]
];

Example

The code for this will be −

const arr = [
   ["John", "[email protected]", "[email protected]"],
   ["John", "[email protected]"],
   ["John", "[email protected]", "[email protected]"],
   ["Mary", "[email protected]"]
];
const recusiveMatch = (included, i, tmp, arr, res) => {
   for(let j = 1; j < arr[i].length; j += 1) {
      let currentEmail = arr[i][j];
      if(included.has(currentEmail)) continue;
      res.push(currentEmail);
      included.add(currentEmail);
      let currentAccountIndexes = tmp.get(currentEmail);
      for(let c = 0; c < currentAccountIndexes.length; c += 1) {
         let currentIndex = currentAccountIndexes[c];
         if(i !== currentIndex) {
            recusiveMatch(included, currentIndex, tmp, arr, res);
         }
      }
   }
};
const merge = (arr) => {
   const tmp = new Map(),
   included = new Set(),
   res = [];
   arr.forEach((account, i) => {
      for(let u = 1; u < account.length; u += 1) {
         let currentEMail = account[u];
         tmp.set(currentEMail, tmp.get(currentEMail) || []);
         tmp.get(currentEMail).push(i);
      }
   });
   arr.forEach((account, i) => {
      if(!included.has(arr[1])) {
         let u = [];
         recusiveMatch(included, i, tmp, arr, u);
         if(u.length) {
            res.push(u);
            u.sort();
            u.unshift(account[0]);
         }
      }
   });
   return res;
};
console.log(merge(arr));

Output

And the output in the console will be −

[
   [
      'John',
      '[email protected]',
      '[email protected]',
      '[email protected]'
   ],
   [ 'John', '[email protected]' ],
   [ 'Mary', '[email protected]' ]
]