如何在链式调用的filter和map之间传递额外数据避免重复查询
方案1:预建索引+单次遍历(性能最优)
首先把需要频繁查询的两个数组提前转成哈希映射,所有查找操作从O(n)降到O(1),同时用reduce一次遍历完成筛选和结果拼装,完全避免重复查询:
function update(records) { // 仅遍历一次生成索引,后续所有查找都是O(1) const peopleMap = new Map(at._people.map(atr => [atr.email.toLowerCase(), atr])); const mailingListMap = new Map(mc.mailingList.map(entry => [entry.id, entry])); return records.reduce((res, mcr) => { const matchPerson = peopleMap.get(mcr.email.toLowerCase()); const listStatus = mailingListMap.get(mcr.id).status.toLowerCase(); if (matchPerson.subscriberStatus.toLowerCase() !== listStatus) { res.push({ id: matchPerson.id, fields: { 'Mailing List Status': mcr.subscriberStatus } }); } return res; }, []); }
方案2:链式调用兼容写法
如果需要保留filter + map的链式写法风格,可以先做一次中间映射,把每个条目对应的查询结果绑定到中间对象上,再做过滤和最终转换:
function update(records) { const peopleMap = new Map(at._people.map(atr => [atr.email.toLowerCase(), atr])); const mailingListMap = new Map(mc.mailingList.map(entry => [entry.id, entry])); return records // 第一步:把原记录和查询到的匹配值、状态对比结果打包成中间对象 .map(mcr => { const match = peopleMap.get(mcr.email.toLowerCase()); return { mcr, match, needUpdate: match.subscriberStatus.toLowerCase() !== mailingListMap.get(mcr.id).status.toLowerCase() } }) // 第二步:过滤出需要更新的条目 .filter(item => item.needUpdate) // 第三步:转换为最终格式 .map(item => ({ id: item.match.id, fields: { 'Mailing List Status': item.mcr.subscriberStatus } })); }
原写法问题说明
filter和map是两次独立的数组遍历,你在外部声明的match变量是所有遍历步骤共享的,filter遍历完全部条目后才会执行map逻辑,因此map里拿到的永远是filter最后一次遍历时赋值的match,无法和每个条目对应。链式调用过程中要传递单条目的中间值,必须将值绑定到对应条目的中间对象上,不能存在全局/外部公共变量中。
额外优化提示:如果at._people和mc.mailingList的数据是固定不频繁更新的,可以把索引生成逻辑提到函数外部,避免每次调用update都重复生成索引,性能还能再提升。
内容的提问来源于stack exchange,提问作者philolegein
相关产品推荐
相关产品推荐

