JavaScript如何通过动态多条件高效过滤对象数组
问题分析与最优实现
先修复现有代码的两个严重bug
- 你定义的
ne(对应is not条件)函数逻辑完全错误,当前返回的是===相等判断,需要改为!==不等判断 - 你示例中
price是字符串类型,直接用大小于号比较会按照字符串字典序计算,比如'100' < '20'会返回true,和数值比较的预期不符,需要先做类型转换
优化思路
你的整体设计逻辑合理,不算过度设计:过滤函数生成和执行逻辑分离,后续新增条件类型、新增or类过滤组都很容易扩展。可以从以下几个点优化性能和可维护性:
- 用条件映射表替代多层
if-else,查找效率更高,也更方便后续扩展新的判断条件 - 先统一把两种格式的
filterGroup转换成过滤条件数组,后续逻辑不用再做格式判断 - 用原生的
Array.filter+Array.every做过滤,every本身就支持短路判断(遇到不满足的条件立刻终止遍历),语义更清晰,也不用自己手写循环和累加逻辑
完整实现代码
// 条件映射表,统一管理所有判断逻辑 const conditionMap = { 'is': (val, compareVal) => val === compareVal, 'is not': (val, compareVal) => val !== compareVal, 'is less than': (val, compareVal) => Number(val) < Number(compareVal), 'is greater than': (val, compareVal) => Number(val) > Number(compareVal) } // 根据filterGroup生成统一的过滤函数 function generateFilter(filterGroup) { const filterList = [] // 统一处理两种格式的filterGroup,收集所有过滤条件 if (filterGroup.type === 'and') { filterList.push(...filterGroup.filters) } else if (filterGroup.type === 'filter') { filterList.push(filterGroup) } // 生成判断函数列表 const checkFns = filterList.map(filter => { const check = conditionMap[filter.condition] return item => check(item[filter.key], filter.value) }) // 返回最终的过滤函数,直接传入options即可得到结果 return options => options.filter(item => checkFns.every(fn => fn(item))) } // 调用示例 const filter = generateFilter(filterGroup) const result = filter(options)
性能说明
这个实现的时间复杂度和你原来的版本完全一致,都是O(n*m):n是options的长度,m是过滤条件的数量,已经是这类过滤需求的理论最优复杂度,没有额外的性能损耗。
内容的提问来源于stack exchange,提问作者Anand Krishnan
相关产品推荐
相关产品推荐

