[英]Create new object based on filtered data
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: 0, 2018: 0, 2019: 402}
没关系,但我需要将日期分成几个月,所以我需要这样的东西:
{ 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 :解决方案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 :解决方案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.该解决方案与 OP 的预期输出有所不同,但我认为它应该符合 OP 的要求。 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.