JavaScript如何编写根据传入键值对过滤字典对象的函数
问题背景
我有一个名为teamData的字典对象:
var teamData = { app: { sortCol:"name", sortDir:"asc" }, data: [ { id: 1, name:"Raptors", coachId: 1, coachFirst: "Ken", coachLast: "jenson", coachPhone: "801-333-4444", coachEmail: "ken.jenson@uvu.edu", coachLicenseLevel: 1, league: 1, division: 1 }, { id: 2, name:"Killer Bunnies", coachId: 2, coachFirst: "Peter", coachLast: "Rabbit", coachPhone: "801-333-4444", coachEmail: "peter.rabbit@uvu.edu", coachLicenseLevel: 1, league: 1, division: 2 }, { id: 3, name:"Thunderbirds", coachId: 3, coachFirst: "Harry", coachLast: "DirtyDog", coachPhone: "801-333-4444", coachEmail: "harry.dirty.dog@uvu.edu", coachLicenseLevel: 2, league: 1, division: 2 } ] }
我需要编写一个接收键值对对象作为入参、返回过滤后结果的函数。例如调用如下代码时:
let teams = filter({coachLicenseLevel:1});
预期返回仅包含2条匹配该键值对元素的过滤结果。
目前已写出部分函数代码,但卡在如何获取过滤对象的键、完成对应值匹配的环节,代码如下:
filter(filterObj) { const v = Object.values(filterObj); const k = Object.keys(filterObj); const res = teamData.filter(({???}) => v.includes(???)); }
实现方案
首先需要纠正第一个基础错误:teamData是外层对象,实际存储队伍列表、需要执行过滤的是它的data属性,不能直接对teamData调用filter方法。
其次你原有逻辑的缺陷很明显:单独提取键和值后直接用includes判断值存在,会出现键值不匹配的误判——比如如果过滤条件是{coachLicenseLevel:1},只要某条数据任意字段值为1就会被判定为匹配,完全不符合预期。正确的判断逻辑是:过滤条件中的所有键值对,必须和当前遍历项的对应属性完全相等,才算匹配成功。
可以按照如下逻辑实现,支持同时传入多个键值对做联合过滤:
function filter(filterObj) { // 提取所有过滤条件的键 const filterKeys = Object.keys(filterObj); // 对队伍数组执行过滤 return teamData.data.filter(item => { // 所有过滤条件全部满足才保留 return filterKeys.every(key => item[key] === filterObj[key]); }); }
如果喜欢更简洁的写法,也可以直接用Object.entries同时拿到键和值遍历:
function filter(filterObj) { const filterEntries = Object.entries(filterObj); return teamData.data.filter(item => filterEntries.every(([key, val]) => item[key] === val) ); }
调用filter({coachLicenseLevel:1})测试时,会自动筛选出coachLicenseLevel属性值为1的两条数据,完全符合预期;如果传入多条件比如filter({coachLicenseLevel:1, division:2}),也会正确返回同时满足两个条件的Killer Bunnies条目。
内容的提问来源于stack exchange,提问作者Brad
相关产品推荐
相关产品推荐

