alezvic
alezvic

Reputation: 374

Create an array of objects from another array grouping duplicates in Javascript

I need to re-organize an array of objects (from a database) into different groups according to one of the attributes of objects. To make it clearer, let's take the following example:

The ORM (Sequelize) returns the following array object:

[
  {
    id: 182,
    employeeId: 'a',
    skillId: 207,   
    score: 3,
  },
  {
    id: 512,
    employeeId: 'a',
    skillId: 212,
    score: 4,
  },
  {
    id: 908,
    employeeId: 'b',
    skillId: 134,
    score: 2,
  },
  {
    id: 876,
    employeeId: 'c',
    skillId: 212,
    score: 3,
  },
]

I need to re-categorize the object grouping the entries by employeeId. Like this:

[
  {
    employeeId: 'a',
    skills: 
           [
             { skillId: 203, score: 3},
             { skillId: 212, score: 4}
           ]
  },
  {
    employeeId: 'b',
    skills: 
           [
             { skillId: 134, score: 2}
           ]
   },
   {
    employeeId: 'c',
    skills: 
           [
             { skillId: 212, score: 3}
           ]
   }
]

It didn't look hard at first but I'm hitting a roadblock, I already tried using reduce, forEarch and map but I only got to make an array of employeeIds, can't really get to include the skills array in each object of the array.

Any help would be appreciated.

Upvotes: 2

Views: 828

Answers (2)

liam.hamblin
liam.hamblin

Reputation: 41

This approach uses classes to build up the employee object and could be easily extended in the future.

const input = [{
    id: 182,
    employeeId: 'a',
    skillId: 207,
    score: 3,
  },
  {
    id: 512,
    employeeId: 'a',
    skillId: 212,
    score: 4,
  },
  {
    id: 908,
    employeeId: 'b',
    skillId: 134,
    score: 2,
  },
  {
    id: 876,
    employeeId: 'c',
    skillId: 212,
    score: 3,
  },
];

const employeeMap = {};

class Skill {
  constructor({
    skillId,
    score
  }) {
    this.skillId = skillId;
    this.score = score;
  }
}

class Employee {
  constructor(rawEmployee) {
    this.employeeId = rawEmployee.employeeId;
    this.skills = [];
  }
  addSkill(rawEmployee) {
    this.skills.push(new Skill(rawEmployee));
  }
}

for (let i = 0; i < input.length; i++) {
  const rawEmployee = input[i];
  let employee = employeeMap[rawEmployee.employeeId];
  if (!employee) {
    employee = new Employee(rawEmployee);
    employeeMap[employee.employeeId] = employee;
  }
  if (employee) {
    employee.addSkill(rawEmployee);
  }
}

const employeeArray = [];

for (let key in employeeMap) {
  employeeArray.push(employeeMap[key]);
}

console.log(employeeArray);
console.log(JSON.stringify(employeeArray));

Upvotes: 2

shlomieb
shlomieb

Reputation: 46

const result = [
  {
    id: 182,
    employeeId: 'a',
    skillId: 207,   
    score: 3,
  },
  {
    id: 512,
    employeeId: 'a',
    skillId: 212,
    score: 4,
  },
  {
    id: 908,
    employeeId: 'b',
    skillId: 134,
    score: 2,
  },
  {
    id: 876,
    employeeId: 'c',
    skillId: 212,
    score: 3,
  },
]



const tempObj = result.reduce((acc, curr) => {
    if (curr.employeeId in acc) {
        acc[curr.employeeId].push({
            skillId: curr.skillId,
            score: curr.score
        })
    } else {
        acc[curr.employeeId] = [{
            skillId: curr.skillId,
            score: curr.score
        }]
    }
    return acc
}, {})

const reorganized = Object.keys(tempObj).map(key => ({
    employeeId: key,
    skills: tempObj[key]
}))

console.log(JSON.stringify(reorganized, null, 2))

Upvotes: 3

Related Questions