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

JavaScript按id关联两个对象数组后按folder分组求和的优化方法

问题描述

需要通过id属性关联两个对象数组(files数组和counts数组),之后按folder属性分组,对每个folder下的所有actions计数累加,最终结果中不需要保留id属性。

文件数组

const files = [{
  id: "xxx",
  folder: "A"
},{
  id: "bbb",
  folder: "B"
},{
  id: "ccc",
  folder: "B"
},{
  id: "ddd",
  folder: "C"
},{
  id: "aaa",
  folder: "C"
},{
  id: "ggg",
  folder: "A"
}]

计数数组

const counts = [{
  id: "bbb",
  actions: {
    download: 5,
    seen: 10,
    shared: 3
  }
},{
  id: "xxx",
  actions: {
    download: 2,
    seen: 5,
    shared: 8
  }
},{
  id: "ccc",
  actions: {
    download: 7,
    seen: 9,
    shared: 5
  }
},{
  id: "ggg",
  actions: {
    download: 0,
    seen: 2,
    shared: 3
  }
},{
  id: "eee",
  actions: {
    download: 50,
    seen: 55,
    shared: 3
  }
},{
  id: "fff",
  actions: {
    download: 5,
    seen: 4,
    shared: 3
  }
}]

期望结果

const result = [{
  folder: "A",
  actions: {
    download: 2,
    seen: 7,
    shared: 11
  }
},{
  folder: "B",
  actions: {
    download: 12,
    seen: 19,
    shared: 8
  }
},{
  folder: "C"
}]

原有实现问题

现有代码通过find方法逐次匹配id,时间复杂度为O(n*m),数组规模大时性能较差;同时存在多次冗余遍历、生成中间数组的问题,可进一步精简。


优化实现方案

核心优化点

  1. 先把counts数组转为以id为键的哈希映射,查找复杂度从O(n)降到O(1),整体时间复杂度降至O(n+m),数组越大性能优势越明显
  2. 跳过中间合并数组的步骤,一次遍历files直接完成关联、分组、累加,减少多余的对象操作和内存占用

优化后代码

命令式写法(可读性最优)

// 构造id到actions的哈希映射
const countMap = new Map(counts.map(item => [item.id, item.actions]));

const groupMap = {};
for (const {id, folder} of files) {
  // 初始化分组
  if (!groupMap[folder]) {
    groupMap[folder] = { folder };
  }
  const actions = countMap.get(id);
  // 存在对应计数就累加
  if (actions) {
    if (!groupMap[folder].actions) {
      groupMap[folder].actions = { download: 0, seen: 0, shared: 0 };
    }
    groupMap[folder].actions.download += actions.download;
    groupMap[folder].actions.seen += actions.seen;
    groupMap[folder].actions.shared += actions.shared;
  }
}

const result = Object.values(groupMap);

函数式写法(更精简)

const countMap = new Map(counts.map(item => [item.id, item.actions]));
const result = Object.values(
  files.reduce((acc, {id, folder}) => {
    acc[folder] ??= { folder };
    const actions = countMap.get(id);
    if (actions) {
      acc[folder].actions ??= { download: 0, seen: 0, shared: 0 };
      acc[folder].actions.download += actions.download;
      acc[folder].actions.seen += actions.seen;
      acc[folder].actions.shared += actions.shared;
    }
    return acc;
  }, {})
);

两种实现输出结果完全符合预期,性能比原实现提升明显。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 19:15:02