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" } // ]
代码逻辑解释
reduce遍历数组中的每一个对象,用一个对象acc作为累加器,键是对象的id,值是对应的对象。- 对于每个元素,判断两种情况:
- 这个ID还没在累加器里,直接存入;
- 累加器里已经有这个ID,但对应的状态是"pending",而当前元素是"complete",就用当前元素覆盖旧的(因为状态更新了)。
- 最后用
Object.values()把累加器的对象值转换成数组,就是我们需要的结果。
为什么比forEach更优?
- 时间复杂度是O(n),只需要遍历数组一次;而如果用forEach配合查找,可能需要多次遍历或者内部循环查找,时间复杂度会变成O(n²),数据量大的时候差距很明显。
- 代码更简洁,逻辑更清晰,不需要额外维护临时数组或者索引。
如果你的场景里同一个ID可能有多个"complete"状态的对象,还可以调整逻辑(比如保留最后一个出现的),只需要把判断条件改成!acc[item.id] || item.status === "complete",这样不管之前是什么状态,只要当前是"complete"就覆盖;或者如果要无条件保留最后一个条目,直接acc[item.id] = item即可。
内容的提问来源于stack exchange,提问作者Sikander
相关产品推荐
相关产品推荐

