如何在JavaScript中为指定年份补全缺失月份的0值?
问题描述
现有如下数据:
const data = [ {time: "2020-10-13", value: 3}, {time: "2020-11-13", value: 30}, {time: "2021-01-13", value: 12}, {time: "2021-02-13", value: 1}, {time: "2021-03-13", value: 23}, {time: "2021-04-13", value: 10}, ... ]
需要将其转换为[月份, 年份, 数值]的二维数组格式,并且补全年份中缺失的月份,缺失月份的数值填0。转换后目标格式示例如下:
[[1, 2020, 0], [2, 2020, 0],[3, 2020, 0], [4,2020, 0],[5, 2020, 0], [6, 2020, 0],[7, 2020, 0],[8, 2020, 0],[9, 2020, 0], [10, 2020, 30],[11, 2020, 3], [12,2020,0], [1, 2021, 12], [2, 2021, 1], ...]
你尝试过的代码:
const months =[1,2,3,4,5,6,7,8,9,10,11,12]; const res = data.flatMap(({time,value}) => { const [y,m,d] = time.split("-").map(Number); const res = months.map((month, i) => { if (m === month) { return [m, y, value] } else { return [month, y, 0] } }) return res; })
const changeData = (data) => { let res = {}; data.forEach((item) => { const {time, value} = item; const [y,m,d] = time.split("-").map(Number); res[y] !== undefined ? res[y].push({m, value}) : res[y] = [{m, value}]; }) return res; } const newData = changeData(data); console.log(newData) const months =[1,2,3,4,5,6,7,8,9,10,11,12]; const formatData = () => { let result = []; for (const [key, value] of Object.entries(newData)) { value.slice(0, 12).map((val, i) => { const y = key; const {m, value} = val; const res = months.map((month, i) => { if (m === month) { result.push([m, y, value]); } else { result.push([month, y, 0]); } }) }) } return result; }
最佳实现方案
核心思路是先建立原始数据的快速查找映射,再按年份和月份顺序生成完整数据:
- 把原始数据转换成
年份-月份为键的映射表,方便快速定位对应月份的数值 - 提取数据中所有年份并排序,确保生成的结果按年份顺序排列
- 对每个年份遍历1-12月,从映射表中取对应值,无数据则填0
具体代码:
const fillMissingMonths = (data) => { // 构建年份-月份到数值的映射,方便快速查找 const valueMap = new Map(); data.forEach(item => { const [year, month] = item.time.split("-").map(Number); valueMap.set(`${year}-${month}`, item.value); }); // 获取所有唯一年份并排序 const allYears = [...new Set(data.map(item => parseInt(item.time.split("-")[0])))] .sort((a, b) => a - b); const result = []; // 遍历每个年份,生成1-12月的完整数据 allYears.forEach(year => { for (let month = 1; month <= 12; month++) { const key = `${year}-${month}`; const value = valueMap.has(key) ? valueMap.get(key) : 0; result.push([month, year, value]); } }); return result; }; // 调用示例 const formattedData = fillMissingMonths(data); console.log(formattedData);
现有代码问题分析
- 第一段代码用
flatMap会为每个原始数据项生成一整年的12条数据,导致同一个年份的同一个月份被重复生成多次(比如2020年10月的原始数据会生成一遍2020年所有月份,11月的原始数据又会再生成一遍,最终结果里2020年的每个月份会出现多次) - 第二段代码的
formatData函数中,遍历年份下的每个原始月份时,又会对该月份生成一遍12条数据,逻辑混乱且会产生大量冗余重复的数据
内容的提问来源于stack exchange,提问作者Julia
相关产品推荐
相关产品推荐

