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

Node.js中如何按年、月两级分组对象数组?

Node.js 按年、月两级分组对象数组的实现方法

需求说明

需要将给定的对象数组按年份和月份进行两级分组,把同年同月的项归为一组,最终得到嵌套结构的分组结果。

初始数据

const items = [
  {month: 11, year: 2022, amount: 10},
  {month: 12, year: 2022, amount: 6},
  {month: 11, year: 2022, amount: 7},
  {month: 12, year: 2022, amount: 12},
  {month: 1, year: 2023, amount: 5},
  {month: 1, year: 2023, amount: 15},
  {month: 11, year: 2023, amount: 30},
  {month: 11, year: 2023, amount: 20}
];

期望结果

const result = {
  "2022": {
    "11": [
      {month: 11, year: 2022, amount: 10},
      {month: 11, year: 2022, amount: 7}
    ],
    "12": [
      {month: 12, year: 2022, amount: 6},
      {month: 12, year: 2022, amount: 12}
    ]
  },
  "2023": {
    "11": [
      {month: 11, year: 2023, amount: 30},
      {month: 11, year: 2023, amount: 20}
    ],
    "1": [
      {month: 1, year: 2023, amount: 5},
      {month: 1, year: 2023, amount: 15}
    ]
  }
};

错误原因分析

你之前尝试的方式出现问题,主要是这两个点:

  1. 对Object.values(itemsPerYear)直接用groupBy:会把所有年份的数组合并成一个大数组,按月份分组后会混合同年份的同月份数据,不符合两级分组的要求。
  2. forEach遍历内部用groupBy返回undefined:大概率是没有将groupBy的结果正确赋值给对应的年份对象属性,导致最终结果没有被正确收集。

正确实现方法

方法1:用Array.prototype.reduce一步到位(原生无依赖)

这是最灵活且兼容性较好的方式,不需要额外依赖库,直接通过reduce构建嵌套结构:

const result = items.reduce((acc, item) => {
  // 确保当前年份对应的容器存在,不存在则初始化空对象
  if (!acc[item.year]) {
    acc[item.year] = {};
  }
  // 确保当前年份下的月份数组存在,不存在则初始化空数组
  if (!acc[item.year][item.month]) {
    acc[item.year][item.month] = [];
  }
  // 将当前项推入对应月份的数组
  acc[item.year][item.month].push(item);
  return acc;
}, {});

console.log(result);

方法2:基于你原有的groupBy思路修正

如果你习惯用groupBy(比如lodash的groupBy或ES2024原生groupBy),可以分两步完成:

场景A:使用lodash的groupBy
const _ = require('lodash');

// 第一步:按年份分组
const itemsPerYear = _.groupBy(items, 'year');
const result = {};

// 第二步:遍历每个年份分组,再按月份分组
Object.entries(itemsPerYear).forEach(([year, yearItems]) => {
  result[year] = _.groupBy(yearItems, 'month');
});

console.log(result);
场景B:使用ES2024原生Array.prototype.groupBy

注意:原生groupBy返回的是Map对象,需要转成普通对象:

// 第一步:按年份分组得到Map
const itemsPerYearMap = items.groupBy(item => item.year);
const result = {};

// 第二步:遍历Map,对每个年份的数组按月份分组并转成对象
for (const [year, yearItems] of itemsPerYearMap) {
  const monthGroupMap = yearItems.groupBy(item => item.month);
  result[year] = Object.fromEntries(monthGroupMap);
}

console.log(result);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:05:21