首页 > 解决方案 > 将值/日期数组列表减少到最后 x 天并添加缺失天数

问题描述

我有以下 JSON,我想获得一个仅包括最后 x 天的数组,并用天和 0 填充空白(没有任何值的天completedstarted

[
   {
      "date":"2019-04-14T22:00:00.000Z",
      "completed":0,
      "started":6
   },
   {
      "date":"2019-04-18T22:00:00.000Z",
      "completed":3,
      "started":1
   },
   {
      "date":"2019-05-19T22:00:00.000Z",
      "completed":0,
      "started":1
   },
   {
      "date":"2019-09-16T22:00:00.000Z",
      "completed":1,
      "started":1
   },
   {
      "date":"2019-08-31T22:00:00.000Z",
      "completed":0,
      "started":2
   },
   {
      "date":"2019-08-10T22:00:00.000Z",
      "completed":0,
      "started":1
   },
   {
      "date":"2019-06-20T22:00:00.000Z",
      "completed":0,
      "started":1
   },
   {
      "date":"2019-07-28T22:00:00.000Z",
      "completed":0,
      "started":4
   },
   {
      "date":"2019-07-30T22:00:00.000Z",
      "completed":0,
      "started":1
   },
   {
      "date":"2019-07-16T22:00:00.000Z",
      "completed":0,
      "started":1
   },
   {
      "date":"2019-08-27T22:00:00.000Z",
      "completed":0,
      "started":1
   }
]

我找不到继续下去的方法。我最初来自一个对象,我在同一日期有多个条目并设法进行此合并,但现在我迷路了。有任何想法吗?我想过filterreduce但我不知道如何应用它们。

谢谢!

期望的输出:

[
   {
      "date": ((today - 7 days)),
      "completed": ...,
      "started": ...
   },
   {
      "date": ((today - 6 days)),
      "completed": ...,
      "started": ...
   },
   {
      "date": ((today - 5 days)),
      "completed": ...,
      "started": ...
   }
]

其中 ((today - x days)) 是过去 7 天的日期,“完成”和“开始”包含上面的值,或者如果不可用,则每个 0。

标签: javascriptarraysreduce

解决方案


您可以使用过滤器仅保留最近 x 天的条目(我在此代码中使用 x 作为变量来表示该天数):

const lastXDays = data.filter(entry => {
  const daysSince = (Date.now() - (new Date(entry.date)).getTime())/1000/60/60/24;
  return daysSince <= x;
});

然后填写额外的天数,因为这些时间戳都在一天中的同一时间(22:00:00),您可以按日期排序,只需将 1 天的毫秒数添加到最小值,直到达到最大值,插入当与当前检查的时间不匹配时:

const sortedDays = lastXDays.sort((a,b) => a.date.getTime() - b.date.getTime());
const maxTime = sortedDays[sortedDays.length - 1].date.getTime();
const minTime = sortedDays[0].date.getTime();
const output = [];
for (let timeToCheck = minTime; timeToCheck <= maxtime; timeToCheck += 1000 * 60 * 60 * 24) {
    const existing = sortedDays.find(day => day.date.getTime() === timeToCheck);
    if (existing) {
      output.push(existing);
    } else {
      output.push({
        date: new Date(timeToCheck),
        completed: 0,
        started: 0
      });
    }
}

推荐阅读