如何基于指定属性数组过滤对象数组(替代大量IF判断的优化方案)
摆脱繁琐IF:优雅处理多状态过滤
嘿,我完全懂你这种被一堆if分支支配的痛苦——硬编码所有filters组合不仅写起来麻烦,以后新增状态还要改一堆代码,太不灵活了。其实只需要两步就能彻底解决这个问题:
第一步:建立状态与属性的映射关系
首先我们把Status枚举里的每个值,和offer对象对应的布尔属性做一个映射表,这样就不用在逻辑里反复对应状态和属性了:
const statusPropertyMap = { [Status.DISCARDED]: 'isDiscarded', [Status.WARNED]: 'isWarned', [Status.COPY]: 'isCopy', [Status.GROUPED]: 'isGrouped' };
第二步:用数组方法简化过滤逻辑
根据你的例子,当filters包含多个状态时,只要offer满足其中任意一个状态对应的属性为true就保留(也就是逻辑或||),这时候用数组的some()方法刚好合适。直接把过滤逻辑写成一行就行:
const filteredOffers = offers.filter(offer => filters.some(status => offer[statusPropertyMap[status]]) );
为什么这比一堆IF好?
- 完全无分支:不管filters是1个、2个还是4个状态,逻辑都不用改,自动适配所有组合
- 可扩展性强:以后新增状态,只需要在
Status枚举和映射表里各加一行,过滤逻辑完全不用动 - 逻辑清晰:
some()方法本身就表达了“只要满足其中一个条件”的语义,读代码的人一眼就能懂
额外需求:如果需要同时满足所有状态(逻辑与&&)
要是你的需求变成“必须满足filters里的所有状态才保留”,只需要把some()换成every()就行:
const filteredOffers = offers.filter(offer => filters.every(status => offer[statusPropertyMap[status]]) );
处理空filters的情况
如果filters是空数组时需要保留所有offer,加个简单判断即可:
const filteredOffers = offers.filter(offer => filters.length === 0 || filters.some(status => offer[statusPropertyMap[status]]) );
这样不管什么场景,代码都简洁又优雅,再也不用写那些头大的if分支啦!
内容的提问来源于stack exchange,提问作者Levi Straus
相关产品推荐
相关产品推荐

