如何按顺序基于另一对象数组过滤目标对象数组?
解决方案:顺序链式过滤数组
要实现按filteredArrayOrderlyOn的顺序依次过滤数组,核心是每一步过滤都基于上一步的结果集,而非每次从头过滤原数组。下面分别给出原生JS和Lodash的实现方案:
原生JavaScript实现
利用数组的reduce方法累积过滤结果,每一步用当前条件处理上一步的输出:
function filterInSequence(array, filters) { // 用原数组副本作为初始值,避免修改原数组 return filters.reduce((currentResult, currentFilter) => { return currentResult.filter(item => { // 确保item满足当前过滤条件的所有键值对(支持多键条件) return Object.entries(currentFilter).every(([key, value]) => { return item[key] === value; }); }); }, [...array]); }
测试示例
假设原数组为:
const arrayA = [ { studentID: 1, Type: "A" }, { studentID: 1, Type: "B" }, { studentID: 2, Type: "A" }, { studentID: 3, Type: "C" } ];
- 先筛
studentID=1,再筛Type=A:
filterInSequence(arrayA, [{ studentID: 1 }, { Type: "A" }]); // 输出: [{ studentID: 1, Type: "A" }]
- 先筛
Type=B,再筛studentID=1:
filterInSequence(arrayA, [{ Type: "B" }, { studentID: 1 }]); // 输出: [{ studentID: 1, Type: "B" }] // 若原数组无符合该顺序过滤的元素,则返回空数组[]
- 仅筛
Type=A:
filterInSequence(arrayA, [{ Type: "A" }]); // 输出: [{ studentID: 1, Type: "A" }, { studentID: 2, Type: "A" }]
Lodash实现
用_.reduce配合_.filter和_.matches,简化条件匹配逻辑:
const _ = require('lodash'); function filterInSequence(array, filters) { return _.reduce(filters, (result, filter) => { // _.matches创建匹配函数,检查对象是否符合filter的键值对 return _.filter(result, _.matches(filter)); }, array); }
这个实现效果和原生JS版本完全一致,只是借助Lodash工具函数减少了手动遍历键值对的代码。
为什么之前会出现重复结果?
大概率是你在过滤时每次都使用原数组而非上一步的结果,或者把所有过滤条件合并成一个对象一次性过滤,没有遵循“依次生效”的规则。比如错误写法可能是:
// 错误示例:一次性合并所有条件,而非顺序过滤 arrayA.filter(item => { return filters.every(filter => { return Object.entries(filter).every(([k, v]) => item[k] === v); }); });
这种写法直接筛选满足所有条件的元素,不区分过滤顺序;或者循环中每次推送原数组的匹配项,也会导致重复。
内容的提问来源于stack exchange,提问作者Tonathiu Redrovan
相关产品推荐
相关产品推荐

