0

I want to group an array of object which i have done using two values office and reportName but i want email id in a string which I am getting but the email id is not unique.i have to try to add all the email but when I try concat it gives an empty string. can anyone knows how to do this

var data = [{
    email: 'amar045@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0455@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0455@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar045@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0445@gmail.com',
    office: 'yyy.in',
    reportName: 'delievered',
  },
  {
    email: 'amar0445@gmail.com',
    office: 'yyy.in',
    reportName: 'delievered',
  },
  {
    email: 'amar0425@gmail.com',
    office: 'yyy.in',
    reportName: 'payroll',
  },

  {
    email: 'amar0425@gmail.com',
    office: 'xyz.in',
    reportName: 'delievered',
  }
];

let hash = Object.create(null);
let grouped = [];

data.forEach(function(o) {
  var key = ['office', 'reportName']
    .map(function(k) {
      return o[k];
    })
    .join('|');

  if (!hash[key]) {
    hash[key] = {
      office: o.office,
      reportName: o.reportName,
      email: ''
    };
    grouped.push(hash[key]);
  }
  ['email'].forEach(function(k) {
    hash[key][k] += o[k].split(',');
  });
});
console.log(grouped);

expected output is

[
  {
    office: 'xyz.in',
    reportName: 'payroll',
     email: 'amar045@gmail.com, amar0455@gmail.com, amar0425@gmail.com'
  },
  {
    office: 'yyy.in',
    reportName: 'delievered',
    email: 'amar0445@gmail.com, amar0425@gmail.com'
  },
  {
    office: 'yyy.in',
    reportName: 'payroll',
    email: 'amar0425@gmail.com'
  }
]
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Does this answer your question? [Group array items using object](https://stackoverflow.com/questions/31688459/group-array-items-using-object) – Mouser Jan 09 '20 at 09:14

3 Answers3

1

If you want to group by office and reportName, then you can reduce method and some method to prevent inserting of duplicates:

const result = [...data.reduce((r, o) => {
    const key = o.office + '-' + o.reportName;
    const item = r.get(key) || Object.assign({}, o, {
        email: []
    });

    if (!item.email.some(s=> s == o.email))
        item.email.push(o.email);

    return r.set(key, item);
}, new Map).values()];

An example:

var data = [
  {
    email: 'amar045@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0455@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0455@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar045@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0445@gmail.com',
    office: 'yyy.in',
    reportName: 'delievered',
  },
  {
    email: 'amar0445@gmail.com',
    office: 'yyy.in',
    reportName: 'delievered',
  },
  {
    email: 'amar0425@gmail.com',
    office: 'yyy.in',
    reportName: 'payroll',
  },

  {
    email: 'amar0425@gmail.com',
    office: 'xyz.in',
    reportName: 'delievered',
  }
];


const result = [...data.reduce((r, o) => {
    const key = o.office + '-' + o.reportName;
    const item = r.get(key) || Object.assign({}, o, {
        email: []
    });

    if (!item.email.some(s=> s == o.email))
        item.email.push(o.email);

    return r.set(key, item);
}, new Map).values()];

console.log(Object.values(result));
StepUp
  • 36,391
  • 15
  • 88
  • 148
1

You can use "includes" method of String to check if the email exists already and update the email attribute of the object.

var data = [
  {
    email: 'amar045@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0455@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0455@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar045@gmail.com',
    office: 'xyz.in',
    reportName: 'payroll',
  },
  {
    email: 'amar0445@gmail.com',
    office: 'yyy.in',
    reportName: 'delievered',
  },
  {
    email: 'amar0445@gmail.com',
    office: 'yyy.in',
    reportName: 'delievered',
  },
  {
    email: 'amar0425@gmail.com',
    office: 'yyy.in',
    reportName: 'payroll',
  },

  {
    email: 'amar0425@gmail.com',
    office: 'xyz.in',
    reportName: 'delievered',
  }
];

let hash = Object.create(null);
let grouped = [];

data.forEach(function(o) {
  var key = ['office', 'reportName']
    .map(function(k) {
      return o[k];
    })
    .join('|');

  if (!hash[key]) {
    hash[key] = {office: o.office, reportName: o.reportName, email: ''};
    grouped.push(hash[key]);
  }
  ['email'].forEach(function(k) {
    if (hash[key] && !hash[key][k].includes(o[k])){
        hash[key][k] += o[k] + ',';
      }
    });
});
console.log(grouped);
0

You can use reduce to group your data according to office and reportName

I've used the Set object as a convenient way to ensure we don't duplicate email addresses.

For example:

const data = [ { email: 'amar045@gmail.com', office: 'xyz.in', reportName: 'payroll', }, { email: 'amar0425@gmail.com', office: 'xyz.in', reportName: 'payroll', }, { email: 'amar0455@gmail.com', office: 'xyz.in', reportName: 'payroll', }, { email: 'amar045@gmail.com', office: 'xyz.in', reportName: 'payroll', }, { email: 'amar0445@gmail.com', office: 'yyy.in', reportName: 'delievered', }, { email: 'amar0425@gmail.com', office: 'yyy.in', reportName: 'delievered', }, { email: 'amar0425@gmail.com', office: 'yyy.in', reportName: 'payroll', }, { email: 'amar0425@gmail.com', office: 'xyz.in', reportName: 'delievered', } ]; 

const result = Object.values(data.reduce((acc, { office, reportName, email} ) => { 
    const key = office + "_" + reportName;
    if (!acc[key]) acc[key] = { office, reportName };
    acc[key].email = [...new Set([...(acc[key].email || []), email])];
    return acc;
}, {}));

console.log("Data grouped by office and reportName:");
console.log(result);
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40