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

如何使用moment和lodash按对象字段分组并按日期范围统计计数?

使用Moment.js和Lodash按字段分组并按日期统计计数

咱们先从基础的按对象字段分组+日期计数需求开始,再一步步拆解你遇到的复杂场景。

一、基础场景:按指定字段分组,统计每组内各日期的出现次数

假设你有如下格式的初始数据:

const rawData = [
  { group: 'Group1', date: '2024-05-01' },
  { group: 'Group1', date: '2024-05-01' },
  { group: 'Group2', date: '2024-05-02' },
  { group: 'Group1', date: '2024-05-03' },
  { group: 'Group2', date: '2024-05-03' },
  { group: 'Group2', date: '2024-05-03' }
];

实现步骤:

  1. 用Lodash的_.groupBy按group字段分组
  2. 对每个分组,用_.countBy结合Moment.js格式化后的日期统计次数

代码示例:

// 第一步:按group字段分组
const groupedByGroup = _.groupBy(rawData, 'group');

// 第二步:转换为带日期计数的结构
const basicResult = _.mapValues(groupedByGroup, (items) => {
  // 按格式化后的日期统计出现次数
  const dateCounts = _.countBy(items, (item) => moment(item.date).format('YYYY-MM-DD'));
  return {
    totalItems: items.length, // 可选:组内总条目数
    dateCounts: dateCounts
  };
});

console.log(basicResult);

输出结果会是:

{
  "Group1": {
    "totalItems": 3,
    "dateCounts": { "2024-05-01": 2, "2024-05-03": 1 }
  },
  "Group2": {
    "totalItems": 3,
    "dateCounts": { "2024-05-02": 1, "2024-05-03": 2 }
  }
}

二、复杂场景:分组后生成完整日期范围的计数(含无数据日期)

针对你提到的「生成startDate到endDate的完整日期范围,每个日期对应计数(无匹配则为0)」的需求,我们需要先生成完整的日期序列,再补全每个分组的日期计数。

1. 先写一个生成日期范围的工具函数

用Moment.js遍历生成指定区间内的所有日期:

function getDateRange(startDateStr, endDateStr) {
  const dates = [];
  let currentDate = moment(startDateStr);
  const endDate = moment(endDateStr);

  // 循环生成日期,直到超过结束日期
  while (currentDate.isSameOrBefore(endDate)) {
    dates.push(currentDate.format('YYYY-MM-DD'));
    currentDate.add(1, 'day');
  }
  return dates;
}

2. 处理分组并生成目标结构

假设你的日期范围是2024-05-01到2024-05-04,代码示例:

const startDate = '2024-05-01';
const endDate = '2024-05-04';
// 生成完整日期范围数组
const fullDateRange = getDateRange(startDate, endDate);

// 第一步:按group字段分组
const groupedData = _.groupBy(rawData, 'group');

// 第二步:转换为包含完整日期计数的结构
const complexResult = _.mapValues(groupedData, (items) => {
  // 先统计现有日期的计数
  const existingDateCounts = _.countBy(items, (item) => moment(item.date).format('YYYY-MM-DD'));
  
  // 构建dates字段:遍历完整日期范围,无匹配则设为0
  const dateCounts = _.fromPairs(
    fullDateRange.map(date => [date, existingDateCounts[date] || 0])
  );

  return {
    dates: dateCounts,
    total: items.length // 可选:组内总条目数
  };
});

console.log(complexResult);

输出结果会包含完整日期范围,即使某日期没有匹配数据也会显示0:

{
  "Group1": {
    "dates": {
      "2024-05-01": 2,
      "2024-05-02": 0,
      "2024-05-03": 1,
      "2024-05-04": 0
    },
    "total": 3
  },
  "Group2": {
    "dates": {
      "2024-05-01": 0,
      "2024-05-02": 1,
      "2024-05-03": 2,
      "2024-05-04": 0
    },
    "total": 3
  }
}

注意事项

  • 确保你的日期格式能被Moment.js正确解析,如果是时间戳、ISO字符串等特殊格式,需要在moment()中指定格式,比如moment(item.date, 'YYYY/MM/DD')
  • 如果日期范围非常大(比如跨年),可以考虑优化日期生成逻辑,但一般业务场景下上述方法足够高效
  • Lodash的_.fromPairs方法用于将二维数组转换为键值对对象,非常适合构建日期计数结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:48:26