summarize array to an Object using reduce function

Viewed 163

I'm tasked with summarizing an array of over 500 other arrays. Here is a sample of some of the entries for var list

var list = [
  [
    "MIKE",               //employee first
    "NGUYEN",             //employee last
    123,                  //id
    "Sandra M.",          //supervisor name 
    "sandra.m@email.com"  //supervisor email
  ],
  [
    "MYA",
    "LANE",
    456,
    "John A",
    "john.a@email.com"
  ],
  [
    "RON",
    "MASTER",
    789,
    "John A",
    "john.a@email.com"
  ],
  [
    "MIKE",
    "NGUYEN",
    123,
    "Sandra M.",
    "sandra.m@email.com"
  ],
  [
    "MYA",
    "LANE",
    456,
    "john A",
    "john.a@email.com"
  ],
  [
    "ROBERT",
    "RULES",
    100,
    "Sandra M.",
    "sandra.m@email.com"
  ],
  [
    "ROBERT",
    "RULES",
    100,
    "Sandra M.",
    "sandra.m@email.com"
  ]
]

I think this would be a great candidate for the reduce function but I can't find a way to use it correctly.

I want to create a simple array of {} that summarizes the data into the following:

var result = [
{
  supervisor: "Sandra M.",   //supervisor name   
  email: sandra.a@email.com, //supervisor email
  employees: 2,              //number of employees supervised by Sandra
  entries: 4                 //total number of items in array with Sandra as the supervisor
},
{
  supervisor: "John A.",     //supervisor name
  email: john.a@email.com,   //supervisor email
  employees: 2,              //number of employees supervised by John
  entries: 3                 //total number of items in array with John as the supervisor
}
]

Here is where I got stuck:

var result= list.reduce(function(all,item){
    all[item[3]] = all[item[3]] || []
    all[item[3]].push({
       supervisor: item[3],
       email: item[4],
       employees: item[2]++,
       entries: item[0]++,
    })
  return all
},{})
1 Answers

The main difficulty here looks to be differentiating an employee from a (non-employee) entry. It looks like all non-employee entry items have 6 items in an input array (including a value for the month), whereas the employees do not have a month. This can be identified pretty easily by checking the length of what you're iterating over.

Reduce into an object indexed by the supervisor email, creating an object at that point if it doesn't exist beforehand. Then, if the item you're iterating over is an employee, increment the employees property (and increment the entries property regardless).

var list = [
  [
    "MIKE",               //employee first
    "NGUYEN",             //employee last
    123,                  //id
    "Sandra M.",          //supervisor name 
    "sandra.m@email.com"  //supervisor email
  ],
  [
    "MYA",
    "LANE",
    456,
    "John A",
    "john.a@email.com"
  ],
  [
    "RON",
    "MASTER",
    789,
    "John A",
    "john.a@email.com"
  ],
  [
    "MIKE",
    "NGUYEN",
    123,
    "Sandra M.",
    "sandra.m@email.com"
  ],
  [
    "MYA",
    "LANE",
    456,
    "February",
    "john A",
    "john.a@email.com"
  ],
  [
    "ROBERT",
    "RULES",
    100,
    "March",
    "Sandra M.",
    "sandra.m@email.com"
  ],
  [
    "ROBERT",
    "RULES",
    100,
    "March",
    "Sandra M.",
    "sandra.m@email.com"
  ]
]

var resultObj = list.reduce(function(all,item){
    const isEmployee = item.length === 5;
    const [supervisor, email] = item.slice(-2);
    if (!all[email]) {
      all[email] = { supervisor, email, employees: 0, entries: 0 };
    }
    if (isEmployee) {
      all[email].employees++;
    }
    all[email].entries++;
    
  return all
},{});
const result = Object.values(resultObj);
console.log(result);

For the new data structure, make a Set of the ids that have been counted as employees. If an item you're iterating over is included in that Set, don't add to the employees count:

var list = [
  [
    "MIKE",               //employee first
    "NGUYEN",             //employee last
    123,                  //id
    "Sandra M.",          //supervisor name 
    "sandra.m@email.com"  //supervisor email
  ],
  [
    "MYA",
    "LANE",
    456,
    "John A",
    "john.a@email.com"
  ],
  [
    "RON",
    "MASTER",
    789,
    "John A",
    "john.a@email.com"
  ],
  [
    "MIKE",
    "NGUYEN",
    123,
    "Sandra M.",
    "sandra.m@email.com"
  ],
  [
    "MYA",
    "LANE",
    456,
    "john A",
    "john.a@email.com"
  ],
  [
    "ROBERT",
    "RULES",
    100,
    "Sandra M.",
    "sandra.m@email.com"
  ],
  [
    "ROBERT",
    "RULES",
    100,
    "Sandra M.",
    "sandra.m@email.com"
  ]
]

const seenIds = new Set();
var resultObj = list.reduce(function(all,item){
    const [id, supervisor, email] = item.slice(-3);
    if (!all[email]) {
      all[email] = { supervisor, email, employees: 0, entries: 0 };
    }
    if (!seenIds.has(id)) {
      all[email].employees++;
      seenIds.add(id);
    }
    all[email].entries++;
    
  return all
},{});
const result = Object.values(resultObj);
console.log(result);

Related