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

JavaScript数组对象过滤:移除id重复且状态从pending转complete的对象

高效处理JSON数组:移除重复ID且状态从pending转为complete的对象

嘿,这个需求我太熟悉了!用分组过滤的方式确实比手动forEach循环匹配要优雅得多,而且性能也更优,尤其是当你的数组数据量比较大的时候。

核心思路是以ID为键分组,优先保留状态为"complete"的对象——毕竟如果同一个ID同时存在"pending"和"complete",说明状态已经更新,我们只需要保留最新的"complete"条目即可。

具体实现代码

先模拟一组测试数据:

const data = [
  { id: 1, status: "pending", content: "A" },
  { id: 2, status: "pending", content: "B" },
  { id: 1, status: "complete", content: "A updated" },
  { id: 3, status: "pending", content: "C" },
  { id: 2, status: "pending", content: "B duplicate" },
  { id: 4, status: "complete", content: "D" }
];

然后用Array.reduce()来完成分组过滤:

const filteredData = Object.values(
  data.reduce((acc, item) => {
    // 如果当前ID还没存入,或者已存的状态是"pending"而当前是"complete",就更新
    if (!acc[item.id] || (acc[item.id].status === "pending" && item.status === "complete")) {
      acc[item.id] = item;
    }
    return acc;
  }, {})
);

console.log(filteredData);
// 输出结果:
// [
//   { id: 1, status: "complete", content: "A updated" },
//   { id: 2, status: "pending", content: "B" },
//   { id: 3, status: "pending", content: "C" },
//   { id: 4, status: "complete", content: "D" }
// ]

代码逻辑解释

  1. reduce遍历数组中的每一个对象,用一个对象acc作为累加器,键是对象的id,值是对应的对象。
  2. 对于每个元素,判断两种情况:
    • 这个ID还没在累加器里,直接存入;
    • 累加器里已经有这个ID,但对应的状态是"pending",而当前元素是"complete",就用当前元素覆盖旧的(因为状态更新了)。
  3. 最后用Object.values()把累加器的对象值转换成数组,就是我们需要的结果。

为什么比forEach更优?

  • 时间复杂度是O(n),只需要遍历数组一次;而如果用forEach配合查找,可能需要多次遍历或者内部循环查找,时间复杂度会变成O(n²),数据量大的时候差距很明显。
  • 代码更简洁,逻辑更清晰,不需要额外维护临时数组或者索引。

如果你的场景里同一个ID可能有多个"complete"状态的对象,还可以调整逻辑(比如保留最后一个出现的),只需要把判断条件改成!acc[item.id] || item.status === "complete",这样不管之前是什么状态,只要当前是"complete"就覆盖;或者如果要无条件保留最后一个条目,直接acc[item.id] = item即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:51:15