You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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. 把原始数据转换成年份-月份为键的映射表,方便快速定位对应月份的数值
  2. 提取数据中所有年份并排序,确保生成的结果按年份顺序排列
  3. 对每个年份遍历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);
现有代码问题分析
  1. 第一段代码用flatMap会为每个原始数据项生成一整年的12条数据,导致同一个年份的同一个月份被重复生成多次(比如2020年10月的原始数据会生成一遍2020年所有月份,11月的原始数据又会再生成一遍,最终结果里2020年的每个月份会出现多次)
  2. 第二段代码的formatData函数中,遍历年份下的每个原始月份时,又会对该月份生成一遍12条数据,逻辑混乱且会产生大量冗余重复的数据

内容的提问来源于stack exchange,提问作者Julia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 13:57:33