Reputation: 105
I have an object which contains arrays of worked dates of two employees, gruped by their id.
var employeeWorkedHours = {
1: [
{ employeeId: 1, hours: 1, date: 7/1/2017},
{ employeeId: 1, hours: 2, date: 7/2/2017},
{ employeeId: 1, hours: 3, date: 7/3/2017},
{ employeeId: 1, hours: 4, date: 7/4/2017},
{ employeeId: 1, hours: 5, date: 7/5/2017}
],
2: [
{ employeeId: 2, hours: 5, date: 7/1/2017},
{ employeeId: 2, hours: 4, date: 7/2/2017},
{ employeeId: 2, hours: 3, date: 7/3/2017},
{ employeeId: 2, hours: 2, date: 7/4/2017},
{ employeeId: 2, hours: 1, date: 7/5/2017}
] }
I want to iterate over it, and merge each array into a single object:
Object.keys(employeeWorkedHours).map((emp) => {
emp.map((day) => {
// expected output: one single object
// { employeeId: X, totalHours: sum of hours of each line }
})}
})}
Thanks
Upvotes: 1
Views: 78
Reputation: 350137
You can use reduce
for that:
const employeeWorkedHours = {
1: [
{ employeeId: 1, hours: 1, date: 7/1/2017},
{ employeeId: 1, hours: 2, date: 7/2/2017},
{ employeeId: 1, hours: 3, date: 7/3/2017},
{ employeeId: 1, hours: 4, date: 7/4/2017},
{ employeeId: 1, hours: 5, date: 7/5/2017}
],
2: [
{ employeeId: 2, hours: 5, date: 7/1/2017},
{ employeeId: 2, hours: 4, date: 7/2/2017},
{ employeeId: 2, hours: 3, date: 7/3/2017},
{ employeeId: 2, hours: 2, date: 7/4/2017},
{ employeeId: 2, hours: 1, date: 7/5/2017}
] };
const result = Object.keys(employeeWorkedHours).map((emp) => {
return employeeWorkedHours[emp].reduce((acc, day) => {
acc.totalHours += day.hours;
return acc;
}, {employeeId: +emp, totalHours: 0} );
});
console.log(result);
Object.keys(employeeWorkedHours)
will give the array of property names of the outer object, so ["1", "2"]
. In the map
callback, emp
will get each of these two values. So employeeWorkedHours[emp]
is the array associated with that key.
Then reduce
will build and return the desired object for that employee as follows: it starts with value {employeeId: +emp, totalHours: 0}
(the second argument to reduce
), which becomes the first argument of the callback, i.e. acc
. The second argument of the callback takes the value of each inner object for that employee (e.g. { employeeId: 1, hours: 1, date: 7/1/2017}
). The hours of that entry are added to the object that is being accumulated (to acc
). The mutated acc
object is returned again to the reduce
internals, which will pass it to the next call of the callback. And so the object is finalised and eventually returned by reduce
.
The result of reduce
is returned to the map
internals, which in turn will return an array of results: one value (object) per employee.
I assume the properties of the main object correspond to the employeeId
of the inner objects. If this is not the case, then you would need to add:
acc.employeeId = day.employeeId;
Upvotes: 2