一次遍历完成分组筛选:ZCode 内置规则 js-combine-iterations 的合并数组遍历实战

发布时间:2026/9/30 7:09:22
一次遍历完成分组筛选:ZCode 内置规则 js-combine-iterations 的合并数组遍历实战
人工智能大模型代码智能体AI Agent桌面应用后端前端CLI【免费下载链接】ZCodeZCode 是 AI 编程工作台提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI以及 Agent CLI 与运行时源码。项目地址https://gitcode.com/zai-org/ZCode点击查看免费下载本文围绕 ZCode 仓库内置的 React/Next.js 性能规则库中js-combine-iterations合并多次数组遍历规则展开讲解多次.filter()/.map()调用为何低效、如何用单次for...of循环完成等价的多次分组筛选并结合源码级原理说明其性能收益与适用边界。读完本文你将掌握在编写与审查 React/TypeScript 前端代码时识别多遍遍历同一数组这一热路径微优化点并安全改写的方法。规则出处ZCode 内置的 Vercel React 性能规则库该规则位于 ZCode 仓库的.agents/skills/react-best-practices/rules/js-combine-iterations.md是仓库随附的React/Next.js 性能优化技能skill中第 7 类JavaScript Performancejs-前缀下的 14 条规则之一。根据技能的入口说明 SKILL.md这套规则库由 Vercel Engineering 维护metadata.json 标注作者为 Vercel Engineering、许可为 MIT按影响度划分为 8 大类别用于指导 Agent 在编写、审查或重构 React/Next.js 代码时自动套用性能模式。规则的 frontmatter 给出了本规则的元信息--- title: Combine Multiple Array Iterations impact: LOW-MEDIUM impactDescription: reduces iterations tags: javascript, arrays, loops, performance ---影响等级LOW-MEDIUM低到中等。这对应 rules/_sections.md 中对该类别的定位——针对热路径hot paths的微优化累积起来可以带来有意义的提升因此它不是关键优先级而是值得在热点代码中落实的优化项。核心主张多个.filter()或.map()调用会让同一个数组被遍历多次应当合并为一次循环。在技能的完整合订参考文档 AGENTS.md 中本规则以第 7.6 节的形式收录内容与独立规则文件完全一致每条规则文件遵循统一的 rules/_template.md 结构frontmatter 元信息 错误示例 正确示例。反例拆解三次独立遍历的真实成本规则给出的错误写法是对同一个users数组做三次独立的.filter()const admins users.filter((u) u.isAdmin); const testers users.filter((u) u.isTester); const inactive users.filter((u) !u.isActive);从表面看这段代码非常直观三个条件、三行调用、三个结果数组。但它的执行模型是第一次filter完整遍历users逐元素执行回调(u) u.isAdmin产生一个新的中间数组admins第二次filter再次从头完整遍历users逐元素执行(u) u.isTester产生testers第三次filter第三次从头完整遍历users执行(u) !u.isActive产生inactive。也就是说当数组长度为n、结果数量合计为k时时间开销约为O(3n)三次完整扫描 三次回调调用开销空间上则额外分配了3 个中间结果数组O(k) 级的内存且包含原数组元素的引用。每一次.filter()调用都带有独立的边界检查、迭代器创建和回调函数调用开销在现代 JavaScript 引擎中这些开销单看很小但在每次渲染都会执行的 React 组件内或在对大数组做高频转换的热路径上多遍扫描的时间与 GC 压力会被成倍放大。这正是规则标题里impactDescription: reduces iterations减少迭代次数的含义它优化的不是单个操作而是同一数据被重复遍历的总次数。正例拆解单次 for...of 循环完成全部分组规则给出的正确写法是把三个筛选条件合并进一次循环const admins: User[] []; const testers: User[] []; const inactive: User[] []; for (const user of users) { if (user.isAdmin) admins.push(user); if (user.isTester) testers.push(user); if (!user.isActive) inactive.push(user); }关键点在于三个if是并列关系而非else if互斥关系。数组中的同一个元素可能同时满足多个条件例如某用户既是 admin 又是 tester因此每个条件都要独立判断、独立push保证结果语义与三个独立filter完全等价。这样整个users数组只被扫描一次时间复杂度从O(3n) 降为 O(n)同时完全消除了三次filter各自产生的中间数组——结果仍然写入admins/testers/inactive三个数组但它们是最终结果而非中间产物。从底层机制看单次遍历还有两个额外收益顺序访问的缓存友好性for...of对数组做单遍顺序访问更贴合现代 CPU 的缓存预取行为而三遍独立遍历会让同一块内存被重复读取三遍避免中间数组的分配与回收.filter()每次调用都会创建一个新数组合并后这一层分配与后续 GC 压力一并消失。一个容易被忽略的差异TypeScript 类型收窄把.filter()改写为for...of时有一个 TypeScript 层面的细节必须注意.filter()支持**类型谓词type predicate**签名可以让结果数组的类型自动收窄。例如const admins users.filter((u): u is Admin u.isAdmin);这里的u is Admin会让 TS 推断出admins的类型为Admin[]。而在for...of循环里user在循环体内仍然是联合类型User收窄需要手动完成例如在push前做显式类型断言或改用users.filter仅用于类型安全、再与分组逻辑拆分。因此改写时建议优先保证类型安全若原有.filter()依赖类型谓词收窄改写后要补充显式类型标注如规则示例中const admins: User[] []的做法仅在热路径且数组较大时才改写规则影响等级仅为 LOW-MEDIUM对于小数组或低频逻辑三次filter的可读性优势反而更值得保留。变式一filter map 链式合并规则只展示了多个.filter()的合并但同一思路完全适用于.filter(...).map(...)这类链式调用——它同样是两遍遍历第一遍过滤产生中间数组第二遍映射产生结果数组// 错误两遍遍历 const names users.filter((u) u.isActive).map((u) u.name); // 正确一遍遍历完成过滤 映射 const names: string[] []; for (const user of users) { if (user.isActive) names.push(user.name); }这个场景在规则库中有专门配套规则 rules/js-flatmap-filter.md当映射与过滤可以合并时flatMap也能在一次遍历中同时完成映射 过滤通过在回调中返回[]来丢弃元素。选择哪种写法取决于可读性偏好flatMap保留了函数式链式风格而for...of对多条件分组这类场景表达力更强。变式二用索引 Map 避免循环内查找合并遍历只解决多遍扫描问题若循环体内还包含按 id 反复查找另一数组的操作会引入额外的 O(n²) 复杂度。规则库中的 rules/js-index-maps.md 与 rules/js-set-map-lookups.md 建议先在循环外构建Map/Set索引把查找降为 O(1)。这两条规则与js-combine-iterations常组合使用先建索引再单遍遍历完成分组与关联。何时应用、何时放弃结合本规则及所属类别的定位_sections.md 中JavaScript Performance类描述为针对热路径的微优化给出明确的适用矩阵建议合并的场景同一数组在每次渲染/每次事件回调中被多次filter/map且数组规模较大数百以上多个筛选条件产生多个结果数组逻辑本身属于一次分组操作结果数组会被反复创建、迅速丢弃频繁触发 GC的场景。不建议合并的场景数组很小几十以内或调用频率极低改写带来的收益远小于可读性损失原有.filter()依赖类型谓词做类型收窄而改写后收窄难以安全表达条件之间存在强互斥关系——此时可考虑else if减少判断次数但这已属于另一类优化且会降低规则示例的可移植性代码由函数式管线风格主导团队更看重链式表达的一致性。在 ZCode 仓库中如何落地ZCode 是一个以 React/TypeScript 构建的 AI 编程工作台桌面应用、浏览器界面与终端 Agent 共用packages/ui等前端源码其前端组件中存在大量基于数组的列表渲染与数据转换逻辑。本规则正是该技能体系用于编写 / 审查 / 重构 React/Next.js 代码时的自动参考之一见 SKILL.md 的触发条件说明。实践中可以这样落地在 React 组件的渲染函数或useMemo依赖计算中检查是否对同一数组连续调用多个.filter()/.map()命中规则场景后按本文正例改写为单次for...of并用显式类型标注保证 TS 收窄安全对照合订文档 AGENTS.md 的第 7.6 节及同类规则js-flatmap-filter、js-index-maps、js-min-max-loop等做联动审查形成一套完整的数组热路径优化清单。小结js-combine-iterations是一条小而准的性能规则它不追求算法层面的颠覆而是消除同一数组被重复遍历这一最常见的热路径浪费——把三次.filter()的 O(3n) 扫描与三份中间数组分配压缩为单次for...of的 O(n) 扫描与零中间数组。规则的影响等级被标注为 LOW-MEDIUM提示开发者把它定位为热路径微优化而非无条件改写项在实际落地时务必同步处理 TypeScript 类型收窄差异并在小数组、低频逻辑上保留可读性更佳的原有写法。掌握了这条规则你就能在 ZCode 这类大型 React 代码库的性能审查中快速识别并安全修复多遍遍历问题。赞分享人工智能大模型代码智能体AI Agent桌面应用后端前端CLI【免费下载链接】ZCodeZCode 是 AI 编程工作台提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI以及 Agent CLI 与运行时源码。项目地址https://gitcode.com/zai-org/ZCode点击查看免费下载相关推荐ZCode 性能规则详解合并多次数组遍历js-combine-iterations——用单次循环替代多次 filter/mapZCode 性能规则详解合并多次数组遍历js combine iterations——用单次循环替代多次 filter/map 本篇技术指南以 ZCodeLangfuse AI 协作技能实践合并多次数组遍历js-combine-iterations 规则详解Langfuse AI 协作技能实践合并多次数组遍历js combine iterations 规则详解 本篇基于 Langfuse 仓库中随附的 Ver人工智能LLMOps可观测性AI 评测LLM 网关后端前端Cherry Studio 规则实践解读合并多次数组遍历的 JS 性能优化js-combine-iterationsCherry Studio 规则实践解读合并多次数组遍历的 JS 性能优化js combine iterations 在 Cherry Studio 仓库人工智能大模型AI 应用交互助手本地部署上一篇Portacle常见误区避免新手在使用便携式Lisp环境时犯的10个错误下一篇history库单元测试实战使用Jest测试路由功能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考