根据过滤后的数据创建新对象

时间:2019-06-16 11:51:38

标签: javascript arrays

我需要一些帮助。我需要计算当年每个月的用户操作量。我有一系列日期:

let years = ['2017', '2018', '2019']
let datesArray = [
    {date: "2019-06-05", userActionsAmount: 88},
    {date: "2019-06-04", userActionsAmount: 314}
]

我有计数对象

let counts = {}

然后我这样迭代:

years.forEach(year => {
          counts[year] = datesArray.filter(singleDay => singleDay.date.slice(0, -6) === year).reduce((acc, obj) => {
            return acc + obj.userActionsAmount
          }, 0)
        })

此代码的计数结果为: {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 }
]}

4 个答案:

答案 0 :(得分:0)

您可以这样做:

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;
})

答案 1 :(得分:0)

您可以在需要时创建属性。 这是两种解决方案:一种是使用数组方法,第二种是更明确的方法。

初始化:

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 = {};

解决方案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);

解决方案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)

为什么要用一个对象数组来表示年值(月数),而不仅仅是一个对象?

答案 2 :(得分:0)

基本上这是一个非常简单的分组

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]);

要使其符合您的格式,您可以执行

之类的操作
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}))
})); 

然后

答案 3 :(得分:0)

此解决方案与OP的预期输出有所不同,但我认为它应该符合OP的要求。如果没有,那大约是获得所需输出的步骤...

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)