如何在JavaScript中从分组对象数组提取按月统计的数值数组?
问题与解决方案
需求概述
现有一个按订阅类型(Basic、Medium等)分组的订阅数组,需要转换为每个订阅类型对应的对象数组,其中每个对象包含label(订阅类型名称)和data(按月统计的count值数组,无数据的月份填0)。例如Basic订阅1月count为4、3月为2,对应data数组为[4,0,2,...]。
原代码仅提取了存在数据的count值,无法对应到具体月份位置,需要调整逻辑实现按月映射。
解决方案
核心思路是:先初始化对应月份数量的全0数组,再遍历每个订阅类型的记录,将count值填充到对应月份的数组位置中。
方法一:固定统计1-12月
如果需要统计全年12个月的数据,代码如下:
// 定义要统计的月份数量(12个月) const totalMonths = 12; const transformedData = subscriptions.map(([label, records]) => { // 初始化全0的data数组 const data = new Array(totalMonths).fill(0); records.forEach(record => { // 从started_at字符串中提取月份(转成数字后减1,对应数组索引,1月→索引0) const monthIndex = parseInt(record.started_at.slice(5, 7), 10) - 1; // 若同一月份有多条记录,可改为累加:data[monthIndex] += record.count data[monthIndex] = record.count; }); return { label, data }; });
方法二:动态适配数据中的月份范围
如果需要根据数据中实际存在的月份范围(最早到最晚月份)生成数组,代码如下:
// 第一步:收集所有记录的月份,确定范围 const allRecordMonths = subscriptions.flatMap(([_, records]) => records.map(item => parseInt(item.started_at.slice(5, 7), 10)) ); const minMonth = Math.min(...allRecordMonths); const maxMonth = Math.max(...allRecordMonths); const monthRangeLength = maxMonth - minMonth + 1; // 第二步:转换数据 const transformedData = subscriptions.map(([label, records]) => { const data = new Array(monthRangeLength).fill(0); records.forEach(record => { const currentMonth = parseInt(record.started_at.slice(5, 7), 10); // 计算当前月份相对于最小月份的索引 const monthIndex = currentMonth - minMonth; data[monthIndex] = record.count; }); return { label, data }; });
代码说明
record.started_at.slice(5,7):从日期字符串中截取月份部分(例如"2022-01-24"截取后为"01")。- 数组索引计算:因为数组从0开始,所以1月对应索引0,通过
月份数字-1得到对应位置;若使用动态范围,则用当前月份-最小月份得到索引。 - 多记录处理:如果同一月份存在多条订阅记录,将赋值语句改为
data[monthIndex] += record.count即可实现count累加。
内容的提问来源于stack exchange,提问作者Abdelhk
相关产品推荐
相关产品推荐

