Reputation: 9
I need to sum minutes
and seconds_left
and group by id_project
.
0: {id_project: 2, minutes: 12, seconds_left: NaN}
1: {id_project: 3, minutes: 15, seconds_left: 11}
2: {id_project: 4, minutes: 0, seconds_left: 11}
3: {id_project: 5, minutes: 0, seconds_left: 2}
4: {id_project: 0, minutes: 0, seconds_left: NaN}
5: {id_project: 1, minutes: 0, seconds_left: NaN}
6: {id_project: 4, minutes: 200, seconds_left: 6}
7: {id_project: 6, minutes: 43, seconds_left: NaN}
8: {id_project: 5, minutes: 100, seconds_left: NaN}
9: {id_project: 2, minutes: 123, seconds_left: NaN}
10: {id_project: 3, minutes: 454, seconds_left: NaN}
11: {id_project: 2, minutes: 89, seconds_left: NaN}
12: {id_project: 5, minutes: 23, seconds_left: NaN}
13: {id_project: 4, minutes: 0, seconds_left: NaN}
14: {id_project: 4, minutes: 11, seconds_left: NaN}
15: {id_project: 3, minutes: 66, seconds_left: NaN}
16: {id_project: 1, minutes: 676, seconds_left: NaN}
I thought of map & reduce, but I can't do this.
Is there any solution to my problem?
Thanks for answers :)
Upvotes: 0
Views: 88
Reputation: 413
First off all ditch the NaN
or convert them to 0 before execution, otherwise arithmetics will all have NaN
value.
Now here's what i did: I created a function to map your array into a new object with unique project IDs, where each one has the total sum of minutes and seconds:
var arr = [
{ id_project: 2, minutes: 12, seconds_left: 1 },
{ id_project: 3, minutes: 15, seconds_left: 11 },
{ id_project: 4, minutes: 0, seconds_left: 11 },
{ id_project: 5, minutes: 0, seconds_left: 2 },
{ id_project: 0, minutes: 0, seconds_left: 2 },
{ id_project: 1, minutes: 0, seconds_left: 3 },
{ id_project: 4, minutes: 200, seconds_left: 6 },
{ id_project: 6, minutes: 43, seconds_left: 3 },
{ id_project: 5, minutes: 100, seconds_left: 3 },
{ id_project: 2, minutes: 123, seconds_left: 10 },
{ id_project: 3, minutes: 454, seconds_left: 2 },
{ id_project: 2, minutes: 89, seconds_left: 2 },
{ id_project: 5, minutes: 23, seconds_left: 3 },
{ id_project: 4, minutes: 0, seconds_left: 4 },
{ id_project: 3, minutes: 66, seconds_left: 5 },
{ id_project: 1, minutes: 676, seconds_left: 5 }
];
var _flatten = function (arr) {
var struct = {}; // We'll use a new flattened structure.
var len = arr.length;
for (var i = 0; i < len; i++) {
var pID = arr[i].id_project;
if (undefined !== struct[pID] && null !== struct[pID]) {
// Already assigned. Sum minutes and seconds to already existing values.
struct[pID].sum =
struct[pID].sum +
(arr[i].minutes * 60) +
arr[i].seconds_left;
}
else {
// Current project ID has not been assigne to new structure. Assign.
struct[pID] = { sum: (arr[i].minutes * 60) + arr[i].seconds_left };
}
}
return struct;
}
The output (sum is in seconds):
_flatten(arr);
0 : {sum: 2}
1 : {sum: 40568}
2 : {sum: 13453}
3 : {sum: 32118}
4 : {sum: 12021}
5 : {sum: 7388}
6 : {sum: 2583}
Upvotes: 1
Reputation: 39250
The following would do what you ask for, you can use map and reduce. I only use map for replacing NaN with 0 and reduce twice, once to get total seconds and once to create hours, minutes, seconds object:
var tmpTotal = [
{id_project: 2, minutes: 12, seconds_left: NaN}
,{id_project: 3, minutes: 15, seconds_left: 11}
,{id_project: 4, minutes: 0, seconds_left: 11}
,{id_project: 5, minutes: 0, seconds_left: 2}
,{id_project: 0, minutes: 0, seconds_left: NaN}
,{id_project: 1, minutes: 0, seconds_left: NaN}
,{id_project: 4, minutes: 200, seconds_left: 6}
,{id_project: 6, minutes: 43, seconds_left: NaN}
,{id_project: 5, minutes: 100, seconds_left: NaN}
,{id_project: 2, minutes: 123, seconds_left: NaN}
,{id_project: 3, minutes: 454, seconds_left: NaN}
,{id_project: 2, minutes: 89, seconds_left: NaN}
,{id_project: 5, minutes: 23, seconds_left: NaN}
,{id_project: 4, minutes: 0, seconds_left: NaN}
,{id_project: 4, minutes: 11, seconds_left: NaN}
,{id_project: 3, minutes: 66, seconds_left: NaN}
,{id_project: 1, minutes: 676, seconds_left: NaN}
]
.map(//set seconds_left to 0 when NaN
item=>
isNaN(item.seconds_left)
? Object.assign({},item,{seconds_left:0})
: item
)
.reduce(//group totals by id
(acc,item)=>{
acc[item.id_project]=acc[item.id_project] || {sum:0};
acc[item.id_project].sum =
acc[item.id_project].sum + item.minutes * 60;
acc[item.id_project].sum =
acc[item.id_project].sum + item.seconds_left;
return acc;
}
,{}
);
console.log(
JSON.stringify(
Object.keys(tmpTotal)//create hours,minutes,seconds from sum object
.reduce(
(acc,key)=>{
acc[key] = {
hours: Math.floor(tmpTotal[key].sum/3600),
minutes: Math.floor((tmpTotal[key].sum%3600)/60),
seconds: tmpTotal[key].sum%60
}
return acc;
}
,{}
)
,undefined
,2
)
);
Upvotes: 0
Reputation: 386560
You could take a hash table as reference to the objects with same id_project
and collect all values for the result.
var array = [{ id_project: 2, minutes: 12, seconds_left: NaN }, { id_project: 3, minutes: 15, seconds_left: 11 }, { id_project: 4, minutes: 0, seconds_left: 11 }, { id_project: 5, minutes: 0, seconds_left: 2 }, { id_project: 0, minutes: 0, seconds_left: NaN }, { id_project: 1, minutes: 0, seconds_left: NaN }, { id_project: 4, minutes: 200, seconds_left: 6 }, { id_project: 6, minutes: 43, seconds_left: NaN }, { id_project: 5, minutes: 100, seconds_left: NaN }, { id_project: 2, minutes: 123, seconds_left: NaN }, { id_project: 3, minutes: 454, seconds_left: NaN }, { id_project: 2, minutes: 89, seconds_left: NaN }, { id_project: 5, minutes: 23, seconds_left: NaN }, { id_project: 4, minutes: 0, seconds_left: NaN }, { id_project: 4, minutes: 11, seconds_left: NaN }, { id_project: 3, minutes: 66, seconds_left: NaN }, { id_project: 1, minutes: 676, seconds_left: NaN }],
temp = {},
result = [];
array.forEach(function (o) {
if (!temp[o.id_project]) {
temp[o.id_project] = { id_project: o.id_project, minutes: 0, seconds_left: 0 };
result.push(temp[o.id_project]);
}
temp[o.id_project].minutes += o.minutes || 0;
temp[o.id_project].seconds_left += o.seconds_left || 0;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 149
If you can iterate over this array, create a new object containing the sum of your array
Something like this
var myArray = [{id_project: 2, minutes: 12, seconds_left: 30},{id_project: 2, minutes: 12, seconds_left: 50},{id_project: 3, minutes: 12, seconds_left: 12}]
var result = {};
myArray.forEach(function (element) {
if (!result.hasOwnProperty(element.id_project))
result[element.id_project] = {minutes : 0, seconds_left : 0};
result[element.id_project].minutes += element.minutes;
result[element.id_project].seconds_left += element.seconds_left;
});
console.log(result);
Upvotes: 0