如何在TypeScript中从时间序列对象数组获取每月最后一天的数据
问题:提取时间序列中每月最后一天的数据
我从API获取了随机日期的时间序列数据,格式如下:
[ { "id": 1, "score": 23, "date": "2023-08-30" }, { "id": 2, "score": 62, "date": "2023-08-22" }, { "id": 3, "score": 82, "date": "2023-07-27" } // ... 更多数据 ]
需要优雅提取序列中每月最后一天的数据,期望结果示例:
[ { "id": 1, "score": 23, "date": "2023-08-30" }, { "id": 3, "score": 82, "date": "2023-07-27" } // ... 更多数据 ]
我目前的代码框架如下:
const getMonthlydata = (allData: Timeseries[]): Timeseries[] => { // Loop over every item to get max date of every month and add it to return array }
解决方案
可以通过按年月分组 + 每组筛选最晚日期的方式实现,逻辑清晰且效率较高:
interface Timeseries { id: number; score: number; date: string; } const getMonthlydata = (allData: Timeseries[]): Timeseries[] => { // 按「年-月」分组,存储每组中日期最晚的那条数据 const monthlyMap = new Map<string, Timeseries>(); allData.forEach(item => { // 提取日期的「年-月」部分作为分组键 const yearMonth = item.date.slice(0, 7); const existingItem = monthlyMap.get(yearMonth); // 若当前分组无数据,或当前条目日期更晚,则更新分组数据 if (!existingItem || new Date(item.date) > new Date(existingItem.date)) { monthlyMap.set(yearMonth, item); } }); // 将Map中的值转为数组返回 return Array.from(monthlyMap.values()); }
逻辑说明:
- 用
Map按年-月(如2023-08)分组,避免重复遍历 - 遍历每条数据时,对比当前分组内已有的最晚日期数据,保留更新的那条
- 最终把Map的value转为数组,得到每个月数据中日期最晚的条目
如果需要严格筛选当月实际最后一天(而非数据中存在的最晚日期),可以加一步验证:
// 辅助函数:判断日期是否为当月最后一天 const isLastDayOfMonth = (dateStr: string): boolean => { const date = new Date(dateStr); // 计算下月第一天,再往前推一天就是当月最后一天 const nextMonthFirstDay = new Date(date.getFullYear(), date.getMonth() + 1, 1); const lastDayOfMonth = new Date(nextMonthFirstDay.getTime() - 24 * 60 * 60 * 1000); return date.toDateString() === lastDayOfMonth.toDateString(); }; // 修改后的方法:仅保留实际当月最后一天的数据 const getMonthlydata = (allData: Timeseries[]): Timeseries[] => { const monthlyMap = new Map<string, Timeseries>(); allData.forEach(item => { const yearMonth = item.date.slice(0, 7); const existingItem = monthlyMap.get(yearMonth); if (!existingItem || new Date(item.date) > new Date(existingItem.date)) { monthlyMap.set(yearMonth, item); } }); // 过滤出符合实际当月最后一天的数据 return Array.from(monthlyMap.values()).filter(item => isLastDayOfMonth(item.date)); }
内容的提问来源于stack exchange,提问作者Annas Rafique
相关产品推荐
相关产品推荐

