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

无for循环下如何按日期映射数组并按日统计各状态ID总数

无for循环实现方案

完全基于数组函数式方法实现,全程不使用任何for关键字开头的循环语法,核心依赖flatMap、reduce、filter、map、Set等原生API实现,符合禁用for循环的代码规范要求。

核心实现代码

// 原始数据源
const sourceData = [
  { id: 'C12-TBX4', studyId: 'TBX4', siteId: 'USA-1', statusType: 'INCOMPLETE', statusFrom: '2020-12-01', statusTo: '2020-12-05' },
  { id: 'C13-TBX4', studyId: 'TBX4', siteId: 'USA-1', statusType: 'INCOMPLETE', statusFrom: '2020-12-03', statusTo: '2020-12-07' },
  { id: 'C14-TBX4', studyId: 'TBX4', siteId: 'USA-1', statusType: 'INCOMPLETE', statusFrom: '2020-12-05', statusTo: '2020-12-08' },
  { id: 'C15-TBX4', studyId: 'TBX4', siteId: null, statusType: 'REJECTED', statusFrom: '2020-12-05', statusTo: '2020-12-08' },
  { id: 'C16-TBX4', studyId: 'TBX4', siteId: null, statusType: 'REJECTED', statusFrom: '2020-12-05', statusTo: '2020-12-09' },
  { id: 'C17-TBX4', studyId: 'TBX4', siteId: 'USA-1', statusType: 'DROPOUT', eligible: true, statusFrom: '2020-12-05', statusTo: '2020-12-09' },
  { id: 'C17-TBX4', studyId: 'TBX4', siteId: 'USA-1', statusType: 'DROPOUT', eligible: false, statusFrom: '2020-12-05', statusTo: '2020-12-10' }
];

// 给定的连续日期序列
const dateSequence = [
  '2020-12-01T00:00:00.000Z',
  '2020-12-02T00:00:00.000Z',
  '2020-12-03T00:00:00.000Z',
  '2020-12-04T00:00:00.000Z',
  '2020-12-05T00:00:00.000Z',
  '2020-12-06T00:00:00.000Z',
  '2020-12-07T00:00:00.000Z',
  '2020-12-08T00:00:00.000Z',
  '2020-12-09T00:00:00.000Z'
];

// 工具:日期转YYYY-MM-DD格式
const formatDay = (dateStr) => new Date(dateStr).toISOString().slice(0, 10);

// 工具:判断日期是否在[from, to)左闭右开区间
const isDateInRange = (checkTs, fromStr, toStr) => {
  const fromTs = new Date(fromStr).getTime();
  const toTs = new Date(toStr).getTime();
  return checkTs >= fromTs && checkTs < toTs;
};

const result = dateSequence.flatMap(currentDate => {
  const currentTs = new Date(currentDate).getTime();
  const currentDay = formatDay(currentDate);

  // 筛选当前日期下所有生效的记录
  const validRecords = sourceData.filter(record => 
    isDateInRange(currentTs, record.statusFrom, record.statusTo)
  );

  // 按studyId、siteId、statusType三个维度分组
  const groupMap = validRecords.reduce((acc, record) => {
    const groupKey = `${record.studyId}||${record.siteId}||${record.statusType}`;
    if (!acc.has(groupKey)) {
      acc.set(groupKey, {
        studyId: record.studyId,
        siteId: record.siteId,
        statusType: record.statusType,
        idSet: new Set()
      });
    }
    acc.get(groupKey).idSet.add(record.id);
    return acc;
  }, new Map());

  // 生成本日期下所有维度的统计条目
  return Array.from(groupMap.values()).map(group => ({
    studyId: group.studyId,
    siteId: group.siteId,
    day: currentDay,
    statusType: group.statusType,
    total: group.idSet.size
  }));
});

逻辑说明

  • 日期判断严格遵循左闭右开规则:statusFrom对应日期计入统计,statusTo对应日期排除,和需求规则完全一致。
  • 用Set存储同分组下的id,自动完成去重,保证total统计的是唯一id的数量,不会重复计数。
  • 自动适配所有statusType类型,不需要单独为每个状态写分支逻辑,后续新增状态类型也不需要修改核心代码。
  • 以传入的连续日期序列为基准生成条目,不会出现日期断层。

注:你提供的INCOMPLETE示例中存在一条重复的2020-12-03条目,上述实现会自动合并同维度同日期的计数,不会生成重复条目,符合常规统计逻辑。如果业务上确实需要保留重复条目,调整分组阶段的处理逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:21:22