You need to enable JavaScript to run this app. JavaScript简化合并同日期同名称数组对象的最优方法(优先jQuery实现)
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript简化合并同日期同名称数组对象的最优方法(优先jQuery实现)

按日期+名称维度合并对象数组的高效实现

方案核心思路

你之前设想的「多轮遍历直到数组长度不再变化」的方案,时间复杂度高达O(n²),数据量稍大就会出现性能卡顿。更高效的做法是单次遍历+字典缓存,整体时间复杂度仅为O(n),不需要反复扫全量数组。
实现逻辑非常简单:

  • 用Map作为缓存容器,存储已经遇到过的「日期+名称」组合对应的合并后条目(用Map比普通JS对象更可靠,不会有原型链键冲突的问题)
  • 遍历原始数组的每一条数据,拼出唯一的分组键:把日期转成时间戳和名称拼接,避免Date对象因为引用不同导致比对失效的问题
  • 如果当前分组键已经在缓存中存在,就把当前条目的l、h、o、c四个数值字段累加到缓存对应条目的数值上
  • 如果当前分组键在缓存中不存在,就把当前条目做浅拷贝后存入缓存
  • 遍历完成后,把缓存中存储的所有条目提取出来,就是最终合并完成的数组

原生JS实现代码

const dataSource = [
  {
    date: new Date(1994, 2, 2),
    name: "a",
    l: 24.00,
    h: 25.00,
    o: 25.00,
    c: 24.875
  },
  {
    date: new Date(1994, 2, 2),
    name: "a",
    l: 23.625,
    h: 25.125,
    o: 24.00,
    c: 24.875
  },
  {
    date: new Date(1994, 2, 3),
    name: "a",
    l: 26.25,
    h: 28.25,
    o: 26.75,
    c: 27.00
  },
  {
    date: new Date(1994, 2, 4),
    name: "c",
    l: 26.50,
    h: 27.875,
    o: 26.875,
    c: 27.25
  }
];

const mergeGroup = (originList) => {
  const cache = new Map();
  originList.forEach(item => {
    // 用时间戳拼接生成分组键,保证同日期同名称的条目能被分到同一组
    const groupKey = `${item.date.getTime()}_${item.name}`;
    if (cache.has(groupKey)) {
      const mergedItem = cache.get(groupKey);
      mergedItem.l += item.l;
      mergedItem.h += item.h;
      mergedItem.o += item.o;
      mergedItem.c += item.c;
    } else {
      // 浅拷贝存入缓存,避免修改原始数组数据
      cache.set(groupKey, {...item});
    }
  });
  return Array.from(cache.values());
}

const mergedResult = mergeGroup(dataSource);

上面的代码运行后得到的结果和你给出的示例结构完全一致。

关于工具函数的说明

jQuery中的$.grep本质是数组筛选方法,只支持根据条件匹配过滤条目,不支持跨条目的聚合累加,用它实现这个场景会非常绕,效率也不高。
如果日常开发中常用Lodash这类工具库,也可以用链式调用写出更简洁的版本,底层逻辑和上面的缓存方案完全一致:

import _ from 'lodash';
const mergedResult = _.chain(dataSource)
  // 按规则分组
  .groupBy(item => `${item.date.getTime()}_${item.name}`)
  // 逐组合并数值字段
  .map(groupItems => ({
    date: groupItems[0].date,
    name: groupItems[0].name,
    l: _.sumBy(groupItems, 'l'),
    h: _.sumBy(groupItems, 'h'),
    o: _.sumBy(groupItems, 'o'),
    c: _.sumBy(groupItems, 'c')
  }))
  .value();

常见踩坑提醒

  • 不要直接把Date对象作为分组键,因为对象类型的键会被隐式转成字符串,同一个日期的两个Date实例可能生成不一样的字符串,导致分组失效
  • 存缓存的时候尽量做浅拷贝,避免后续修改合并后的数组影响原始数据源
  • 不要用「多轮循环直到数组长度不变」的方案,数组规模超过100条时性能就会明显低于单次遍历的方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 15:45:03