如何在JavaScript中过滤嵌套对象数组?按科目分数筛选学生
对象数组过滤解决方案
需求说明
从给定的students数组中筛选出满足以下条件的学生:学生拥有至少一个科目,其名称和分数与filters数组中的某一项完全匹配,目标结果为保留Alan和Megan。
示例数据
const students= [ { id: 1, name: "Alan", subjects: [ { name: "math", mark: 5 }, { name: "poetry", mark: 4 }, { name: "physics", mark: 3 } ] }, { id: 2, name: "Joe", subjects: [ { name: "geography", mark: 5 }, { name: "music", mark: 5 }, { name: "literature", mark: 3 } ] }, { id: 3, name: "Megan", subjects: [ { name: "math", mark: 4 }, { name: "physics", mark: 3 } ] } ]; const filters = [ { name: "math", mark: 5 }, { name: "physics", mark: 3 } ];
原代码问题分析
你之前的代码无法得到正确结果,核心问题有两个:
- 属性名错误:学生对象中存储科目的属性是
subjects,但代码中误用了x.skills,导致无法读取正确数据。 - 对象匹配逻辑错误:
indexOf是基于引用查找数组元素,无法判断两个对象的值是否相等(filters中的对象和学生subjects中的对象是不同引用),因此永远返回-1,过滤结果为空。
正确实现方案
基础版本
使用filter遍历学生数组,结合some方法检查每个学生的科目是否存在匹配项:
const filteredStudents = students.filter(student => { // 检查当前学生是否有至少一个科目匹配filters中的任意一项 return student.subjects.some(subject => { return filters.some(filter => filter.name === subject.name && filter.mark === subject.mark); }); }); console.log(filteredStudents); // 输出包含Alan和Megan的数组
优化版本(大数据量场景)
如果处理的数据量较大,可先将filters转换为字符串集合,减少重复匹配的计算量:
// 将过滤项转换为唯一字符串存入Set,提升匹配效率 const filterSet = new Set(filters.map(item => `${item.name}:${item.mark}`)); const filteredStudents = students.filter(student => { return student.subjects.some(subject => { // 检查当前科目是否在过滤集合中 return filterSet.has(`${subject.name}:${subject.mark}`); }); });
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

