如何将多个Array.filter合并为单个,或采用更高效的方式优化冗余代码?
重复数组过滤统计逻辑优化方案
问题场景
现有重复的数组过滤统计逻辑,存在代码冗余、多次遍历数组带来的不必要性能损耗,需求为将多次filter操作合并为单次遍历,或找到更高效的实现方式,同时确认直接使用for循环实现是否可行。
原有代码如下:
driving += value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'driving').length; breathWork += value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'breath work').length; meditation += value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'meditation').length; cooking += value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'cooking').length; walking += value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'walking').length; other += value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'other').length;
优化方案
完全可以合并为单次遍历实现,比原有多次filter的性能提升数倍,以下是两种常用实现:
方案1:Array.reduce实现(简洁易读)
仅遍历数组1次,符合函数式编码风格:
// 初始化统计映射表 const practiceCount = value.reduce((acc, item) => { // 跳过非目标类型的项 if (item.type !== CalendarEventType.MIND) return acc; const currentPractice = item.data.practice; // 匹配到统计项则计数+1 if (Object.prototype.hasOwnProperty.call(acc, currentPractice)) { acc[currentPractice]++; } return acc; }, { driving: 0, 'breath work': 0, meditation: 0, cooking: 0, walking: 0, other: 0 }); // 赋值到对应变量 driving += practiceCount.driving; breathWork += practiceCount['breath work']; meditation += practiceCount.meditation; cooking += practiceCount.cooking; walking += practiceCount.walking; other += practiceCount.other;
方案2:普通for循环实现(性能最优)
处理万级以上大数组时性能略高于reduce,无额外函数调用开销:
const practiceCount = { driving: 0, 'breath work': 0, meditation: 0, cooking: 0, walking: 0, other: 0 }; const arrLength = value.length; for (let i = 0; i < arrLength; i++) { const item = value[i]; if (item.type !== CalendarEventType.MIND) continue; const currentPractice = item.data.practice; if (practiceCount[currentPractice] !== undefined) { practiceCount[currentPractice]++; } } driving += practiceCount.driving; breathWork += practiceCount['breath work']; meditation += practiceCount.meditation; cooking += practiceCount.cooking; walking += practiceCount.walking; other += practiceCount.other;
额外优化收益
- 可维护性提升:后续新增需要统计的practice类型时,仅需在初始化的统计对象中添加对应key即可,无需新增独立的filter逻辑
- 可复用性提升:可以将该统计逻辑封装为通用工具函数,同类统计场景可直接复用
内容的提问来源于stack exchange,提问作者user2994290
相关产品推荐
相关产品推荐

