i need some help. I need to calculate the amount of user actions in each month of current year. I have an array of dates:
let years = ['2017', '2018', '2019']
let datesArray = [
{date: "2019-06-05", userActionsAmount: 88},
{date: "2019-06-04", userActionsAmount: 314}
]
and i have the count object
let counts = {}
then i iterate thru this like that:
years.forEach(year => {
counts[year] = datesArray.filter(singleDay => singleDay.date.slice(0, -6) === year).reduce((acc, obj) => {
return acc + obj.userActionsAmount
}, 0)
})
with this code result of counts is: {2017: 0, 2018: 0, 2019: 402}
wich is ok, but i need to break the date in to months, so i need something like this:
{ 2017: []},
{ 2018: []}
{ 2019: [
{ '01': 0 },
{ '02': 0 },
{ '03': 0 },
{ '04': 0 },
{ '05': 0 },
{ '06': 402 },
{ '07': 0 },
{ '08': 0 },
{ '09': 0 },
{ '10': 0 },
{ '11': 0 },
{ '12': 0 }
]}
you can do it like this:
let datesArray = [ {date: "2019-06-05", userActionsAmount: 88}, {date: "2019-06-04", userActionsAmount: 314} ] let result={}; datesArray.forEach(dateItem=>{ let date=dateItem.date.split("-"); let year=date[0]; let month=date[1]; if(!result[year]) result[year]={}; if(!result[year][month]) result[year][month]=0; result[year][month]+=dateItem.userActionsAmount; })
You could create properties when needed. Here are two solutions : one with array methods and second more explicit.
Initialization :
const monthsKeys = ["01", "02", "03","04", "05", "06", "07", "08", "09", "10", "11", "12"];
const years = ['2017', '2018', '2019'];
const datesArray = [
{date: "2019-06-05", userActionsAmount: 88},
{date: "2019-06-04", userActionsAmount: 314}
];
const counts = {};
Solution 1 :
years.forEach( y => { counts[y] = []; });
datesArray.forEach(dateCount => {
const [year, month, day] = dateCount.date.split("-");
if (counts[year].length === 0) monthsKeys.forEach(m => {counts[year].push({[m] : 0});});
counts[year][Number(month) - 1][month] += dateCount.userActionsAmount;
});
console.log(counts);
Solution 2 :
// fill counts with years
for (const y of years) {
counts[y] = [];
}
// fill counts with months and count
for (const e of datesArray) {
const splittedDate = e.date.split("-");
const year = splittedDate[0];
const month = splittedDate[1];
// create year if needed, not necessary if years array is sure
if ( ! year in counts) {
counts[year] = [];
}
// create monthes if needed
if (counts[year].length === 0) {
for (const m of monthsKeys) {
counts[year].push({[m]: 0});
}
}
// add value
counts[year][Number(month) - 1][month] += e.userActionsAmount;
}
console.log(counts)
Why an array of objects for year values (months counts) and not simply an object?
That's basically a very simple grouping
const datesArray = [ {date: "2019-06-05", userActionsAmount: 88}, {date: "2019-06-04", userActionsAmount: 314} ]; const groupedByMonth = datesArray.reduce((a, b) => a.set(b.date.substring(0,7), ~~a.get(b.date.substring(0,7)) + b.userActionsAmount), new Map); console.log([...groupedByMonth]);
To get it to your format, you could do something like
const yourFormat = years.map(e => ({
[e]: Array.from(groupedByMonth).filter(([k, v]) => k.substring(0,4) === e).map(([k, v]) => ({[k.substring(5,7)]: v}))
}));
then
This solution has some varation from the OP's expected output, but I believe that it should fit OP's requirements. If not, it's about a step to get the output as desired...
const years = [2017, 2018, 2019] const dates = [{ date: "2019-06-05", userActionAmount: 88 }, { date: "2019-06-04", userActionAmount: 314 } ] const transform = (years, dates) => dates.reduce( (output, { date, userActionAmount, parsedDate = new Date(date), year = parsedDate.getFullYear(), month = parsedDate.getMonth() + 1, yearData = output[year] }) => (yearData[month] += userActionAmount) && output, Object.fromEntries(years.map(year => [year, Object.fromEntries(Array.from({ length: 12 }, (_, x) => [x + 1, 0]))]))) const output = transform(years, dates) console.log(output) // This output lets you get total amount // of some given month in the following way: const monthAmount = output[2019][6] console.log (monthAmount)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.