I have an array like this (count and date)
day = [
{ count: 1, date: '2022-07-07' },
{ count: 1, date: '2022-08-14' },
{ count: 2, date: '2022-07-19' },
{ count: 4, date: '2022-07-19' },
{ count: 2, date: '2021-01-19' },
{ count: 2, date: '2021-03-02' }
]
now I am looking for a new array, it should be total count week/month/year base
I am expecting like this below
month = [
{ count: 7, date: '2022-07-01' },
{ count: 1, date: '2022-08-01' },
{ count: 2, date: '2021-01-01' },
{ count: 2, date: '2021-03-01' }
]
year = [
{ count: 9, date: '2022-01-01' },
{ count: 4, date: '2021-01-01' },
]
Same like week bases as well
I am trying to achieve something like this
let month;
for( d of day ) {
if(condition) {
// calculation for count adding
month.push(d)
}
}
CodePudding user response:
Updated the answer based on RobG suggestions.
I didn't implement the groupByWeek() part, but the implementation of this part should be similar to groupByMonth() and groupByYear() function in below code.
For the groupByWeek part, the tricky part is how to get the week number of the date, I think the getWeek() function from cmgchess shared codes in the above comment section would be helpful, or you can use a date library to get the week number.
let day = [
{ count: 1, date: "2022-07-07" },
{ count: 1, date: "2022-08-14" },
{ count: 2, date: "2022-07-19" },
{ count: 4, date: "2022-07-19" },
{ count: 2, date: "2021-01-19" },
{ count: 2, date: "2021-03-02" },
{ count: 5, date: "2021-07-19" },
];
// create a map of {$year-$month-01: $count} based on the data in day array
let groupByMonth = day.reduce((partialCount, item) => {
let dateSplit = item.date.split("-");
let y = dateSplit[0];
let m = dateSplit[1];
if (Object.prototype.hasOwnProperty.call(partialCount, `${y}-${m}-01`)) {
partialCount[`${y}-${m}-01`] = item.count;
} else {
partialCount[`${y}-${m}-01`] = item.count;
}
return partialCount;
}, {});
// convert the groupByMonth map into an array of object(your expected format)
let monthList = Object.keys(groupByMonth).map(key => {
return {
count: groupByMonth[key],
date: key
};
});
// create a map of {$year-01-01: $count} based on the data in day array
let groupByYear = day.reduce((partialCount, item) => {
let dateSplit = item.date.split("-");
let y = dateSplit[0];
if (Object.prototype.hasOwnProperty.call(partialCount, `${y}-01-01`)) {
partialCount[`${y}-01-01`] = item.count;
} else {
partialCount[`${y}-01-01`] = item.count;
}
return partialCount;
}, {});
// convert the groupByMonth map into an array of object(your expected format)
let yearList = Object.keys(groupByYear).map(key => {
return {
count: groupByYear[key],
date: key
};
});
console.log("month:", monthList);
console.log("year:", yearList);
CodePudding user response:
I implemeted a solution that return an object
with :
key => value = month / year => totalCount
I hope the output is okay for your, it lookes more logical to me than use only one date
of the month / year
to name it.
By the way I can change the output format if it is a problem or you ;)
Here is the code :
const toArray = obj => Object.keys(obj).map(k => [k, obj[k]]); // transform an object to array of array [[key], [value]];
const sum = arr => arr.reduce((ps, a) => ps a, 0); // sum an array
let day = [
{ count: 1, date: '2022-07-07' },
{ count: 1, date: '2022-08-14' },
{ count: 2, date: '2022-07-19' },
{ count: 4, date: '2022-07-19' },
{ count: 2, date: '2021-01-19' },
{ count: 2, date: '2021-03-02' }
];
let years = Object.fromEntries( // transform the result to an object
toArray( // transform the object to array
day.reduce((acc, x) => { // sort the day by month / year
// key (month or year) doesn't exist => create the key => append the element
(acc[x.date.split('-').at(0)] = acc[x.date.split('-').at(0)] || []).push(x.count);
return acc;
}, {})
).map(arr => [arr.at(0), sum(arr.at(1))]) // sum the counts
);
let months = Object.fromEntries(toArray(day.reduce((acc, x) => {
(acc[x.date.split('-').at(1)] = acc[x.date.split('-').at(1)] || []).push(x.count);
return acc;
}, {})).map(arr => [arr.at(0), sum(arr.at(1))]));
console.log(months);
console.log(years);