JavaScript Lodash如何实现含字符串、ID数组的多条件集合筛选
Lodash多条件筛选支持数组匹配方案
问题背景
使用Lodash对集合做筛选时,字符串类型的等值筛选条件可正常生效,但需要同时实现两类规则:
location字段的id匹配指定ID数组中的任意值status字段匹配指定字符串
直接将筛选条件写为"location":{"id" :["1","4"]}无法得到预期结果,原有实现代码如下:
const collection = [ {account: {id: "1", name: "a"}, location:{id: "1", name: "x"}, status: "ok"}, {account: {id: "2", name: "b"}, location:{id: "2", name: "x"}, status: "ok"}, {account: {id: "3", name: "c"}, location:{id: "4", name: "y"}, status: "failed"}, {account: {id: "4", name: "d"}, location:{id: "4", name: "y"}, status: "ok"}, ] let filterByConditions = { "location":{"id" :"1"}, "account":{ "id": "1"}, "status": "ok", }; let results = _.filter(collection, filterByConditions);
失效原因
_.filter传入普通对象作为筛选参数时,默认执行深度全等匹配,不会自动将数组值识别为「匹配任意项」规则。上述数组写法会被判定为需要匹配location.id字段值本身等于["1","4"]数组,和集合内的字符串类型id值类型不匹配,因此无法命中结果。
实现方法
写法1:直接自定义筛选谓词(简单场景推荐)
针对明确的筛选规则,直接在_.filter的回调中写判断逻辑即可,可读性最高:
const results = _.filter(collection, item => { return ( item.status === "ok" && ["1", "4"].includes(item.location.id) // 其他等值条件可以直接追加 && item.account.id === "1" ) })
上述代码运行后会返回符合要求的条目:{account: {id: "1", name: "a"}, location:{id: "1", name: "x"}, status: "ok"}。
写法2:封装通用筛选生成器(复杂多条件场景推荐)
如果筛选条件动态变化,可以封装通用转换函数,自动识别数组类型条件走「包含匹配」、单值条件走「全等匹配」,兼容原有写法的同时支持数组规则:
function createLodashFilter(conditions) { return (item) => { return _.every(conditions, (ruleVal, rulePath) => { const fieldVal = _.get(item, rulePath); if (Array.isArray(ruleVal)) { return _.includes(ruleVal, fieldVal); } return _.isMatch(item, _.set({}, rulePath, ruleVal)); }) } } // 使用方式 const filterByConditions = { "location.id": ["1", "4"], // 数组自动走包含匹配 "status": "ok", "account.id": "1" // 单值自动走全等匹配 }; const results = _.filter(collection, createLodashFilter(filterByConditions));
内容的提问来源于stack exchange,提问作者SDLP
相关产品推荐
相关产品推荐

