Reputation: 69
I have the following data objects in a list within in my React project:
{projectId: "11111", startTime: "Mon May 11 2020 19:19:07", duration: "15"}
{projectId: "22222", startTime: "Mon May 11 2020 19:24:07", duration: "45"}
{projectId: "11111", startTime: "Mon May 11 2020 19:45:07", duration: "15"}
{projectId: "11111", startTime: "Tue May 12 2020 11:00:07", duration: "30"}
{projectId: "22222", startTime: "Tue May 12 2020 12:19:07", duration: "15"}
I want to be able to group and sum this data by Date and ProjectId so i would expect the following output:
{projectId: "11111", Date: "Mon May 11 2020", TotalDuration: "30"}
{projectId: "22222", Date: "Mon May 11 2020", TotalDuration: "45"}
{projectId: "11111", Date: "Tue May 12 2020", TotalDuration: "30"}
{projectId: "22222", Date: "Tue May 12 2020", TotalDuration: "15"}
I am new to ReactJS and can not seem to find a solution to do this.
Upvotes: 0
Views: 1114
Reputation: 15442
you can try to group your data by productId
+ date without the time part, using Array.reduce()
:
const data = [
{projectId: "11111", startTime: "Mon May 11 2020 19:19:07", duration: "15"},
{projectId: "22222", startTime: "Mon May 11 2020 19:24:07", duration: "45"},
{projectId: "11111", startTime: "Mon May 11 2020 19:45:07", duration: "15"},
{projectId: "11111", startTime: "Tue May 12 2020 11:00:07", duration: "30"},
{projectId: "22222", startTime: "Tue May 12 2020 12:19:07", duration: "15"}
];
const result = data.reduce((res, curr) => {
// remove time
const date = curr.startTime.substr(0, curr.startTime.length - 9);
// build the key (productId + date without the time part)
const key = `${curr.projectId}_${date}`;
res[key] = res[key] || {
projectId: curr.projectId,
Date: date,
TotalDuration: "0"
};
// sum durations as integers and convert the sum back to string
res[key].TotalDuration = (+res[key].TotalDuration + +curr.duration) + '';
return res;
}, {});
// print only values
console.log(Object.values(result));
BTW: the solution is in plain JS (nothing React specific)
Upvotes: 1
Reputation: 9357
You can do this:
const groupedDataObj = {};
for(let entry of oridinalData) {
const regexDate = /^([A-Za-z]){3} ([A-Za-z]){3} \d{2} \d{4}/;
const key = entry.projectId + '||' + entry.startTime.split(regexDate)[0]
if(!groupedDataObj.hasOwnProperty(key)) {
groupedDataObj[key] = { totalDuration: 0 };
}
groupedDataObj[key].totalDuration += +entry.TotalDuration;
}
const groupedData = Object.keys(groupedDataObj).map(key => {
const splittedKey = key.split('||');
const productId = splittedKey[0];
const Date = splittedKey[1];
return {
productId,
Date,
TotalDuration: groupedDataObj[key].totalDuration
};
});
Upvotes: 0
Reputation: 51816
You can do this, though I'd recommend using an ISO-format datetime string instead of this format for startTime
, since the Date
constructor is not guaranteed to be able to parse this format in every implementation.
const data = [
{projectId: "11111", startTime: "Mon May 11 2020 19:19:07", duration: "15"},
{projectId: "22222", startTime: "Mon May 11 2020 19:24:07", duration: "45"},
{projectId: "11111", startTime: "Mon May 11 2020 19:45:07", duration: "15"},
{projectId: "11111", startTime: "Tue May 12 2020 11:00:07", duration: "30"},
{projectId: "22222", startTime: "Tue May 12 2020 12:19:07", duration: "15"}
];
const updateOrCreate = (map, key, update, create) => map.set(
key,
update(map.has(key) ? map.get(key) : create())
);
const sums = [
...data.map(
o => ({ ...o, Date: new Date(o.startTime).toDateString() })
).reduce(
(outer, o) => updateOrCreate(
outer,
o.Date,
inner => updateOrCreate(
inner,
o.projectId,
sum => +o.duration + sum,
() => 0
),
() => new Map()
),
new Map()
)
].flatMap(
([Date, projects]) => [...projects].map(
([projectId, duration]) => ({
projectId, Date, TotalDuration: `${duration}`
})
)
);
console.log(sums);
Upvotes: 1
Reputation: 1242
You can use reduce and filter for group your items:
const items = [{projectId: "11111", startTime: "Mon May 11 2020 19:19:07", duration: "15"},
{projectId: "22222", startTime: "Mon May 11 2020 19:24:07", duration: "45"},
{projectId: "11111", startTime: "Mon May 11 2020 19:45:07", duration: "15"},
{projectId: "11111", startTime: "Tue May 12 2020 11:00:07", duration: "30"},
{projectId: "22222", startTime: "Tue May 12 2020 12:19:07", duration: "15"}]
const trimTime = (dateTime) => dateTime.split(' ').splice(0, 4).join(' ')
const groupItems = items.reduce((acc,rec) => {
const itemsInAcc = acc.filter(a=>a.projectId === rec.projectId && a.startTime === trimTime(rec.startTime))
if (itemsInAcc.length > 0) {
itemsInAcc[0].duration = (+itemsInAcc[0].duration) + (+rec.duration)
}
else {
acc = [...acc, {...rec, startTime: trimTime(rec.startTime)}]
}
return acc
}, [])
Upvotes: 1