Home > database >  Creating an object which contains unique item from a nested array
Creating an object which contains unique item from a nested array

Time:04-09

I have an array of objects called employees. I need a solution that will return me a list of groups and respective employees present in the group along with the group properties. The example is below, I have used an object but the result can also be an array that has a property called groupName within an object. [{groupName:"developer", employees:[],...}..] As long as the response returns a list of groups with their corresponding employees.

Below is the solution I did but I need a solution with a better time complexity that is O(n).

const employees = [
  { "name": "John Doe",
    "id": "1",
    "groups": [
      { "id": "developerId", "name": "developer", "color": "#fff" },
      { "id": "engineerId",  "name": "engineer", "color": "#fff" }
    ],
    "groupId":["developerId", "engineerId"]
  },
  { "name": "Jane Doe",
    "id": "2",
    "groups": [
      { "id": "developerId", "name": "developer", "color": "#fff" },
      { "id": "testerId",  "name": "tester", "color": "#fff" }
    ],
    "groupId":["developerId", "testerId"]
  }
]

//Solution O(m*n)
 let groups = {};
  employees.forEach((item) => {
    item.groups.forEach((group) => {
      if (!groups[group.name]) {
        groups[group.name] = {
          employees: [item.id],
          ...group,
        };
      } else {
        groups[group.name].employees = [...groups[group.name].employees, item.id];
      }
    });
  });

//result
{
    "developer":{
        "id":"developerId",
        "employee":[
           "1",
           "2"
        ],
        "color":"#fff"
    },
    "engineer":{
        "id":"employeeId",
        "employee":[
            "1",
         ],
         "color":"#fff"
    },
    "tester":{
        "id":"testerId",
        "employee":[
            "2",
         ],
         "color":"#fff"
    }
}

CodePudding user response:

Using Array#reduce and Array#forEach:

const employees = [
  { 
    "name": "John Doe",
    "id": "1",
    "groups": [
      { "id": "developerId", "name": "developer", "color": "#fff" },
      { "id": "engineerId", "name": "engineer", "color": "#fff" }
    ],
    "groupId": ["developerId", "engineerId"]
  },
  { 
    "name": "Jane Doe",
    "id": "2",
    "groups": [
      { "id": "developerId", "name": "developer", "color": "#fff" },
      { "id": "testerId", "name": "tester", "color": "#fff" }
    ],
    "groupId": ["developerId", "testerId"]
  }
];

const groups = employees.reduce((acc, { id: employeeId, groups = [] }) => {
  groups.forEach(({ id, name, color }) => {
    acc[name] = { 
      id, color, employee: [...(acc[name]?.employee ?? []), employeeId] 
    };
  });
  return acc;
}, {});

console.log(groups);

CodePudding user response:

If you like to add some speed, you could use the old fashioned for statement for iterating, especially of having only a single result object.

This approach does not create an object again and again and uses the already existing objects.

const
    employees = [{ name: "John Doe", id: "1", groups: [{ id: "developerId", name: "developer", color: "#fff" }, { id: "engineerId", name: "engineer", color: "#fff" }], groupId: ["developerId", "engineerId"] }, { name: "Jane Doe", id: "2", groups: [{ id: "developerId", name: "developer", color: "#fff" }, { id: "testerId", name: "tester", color: "#fff" }], groupId: ["developerId", "testerId"] }],
    result = {};

for (const { id: employeeId, groups } of employees) {
    for (const { id, name, color } of groups) {
        result[name] ??= { id, color, employee: [] };
        result[name].employee.push(employeeId);
    }
}

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

  • Related