如何根据人员姓名过滤嵌套结构的数组?
按人员姓名过滤嵌套数组的问题
原始数据结构
[ { "label": "Group A", "fields": [ { "value": "color1", "name": "Mike" }, { "value": "color2", "name": "Mark" } ] }, { "label": "Group B", "fields": [ { "value": "red", "name": "Steve" }, { "value": "priority", "name": "Laura" } ] }, { "label": "Group C", "fields": [ { "value": "red", "name": "Paul" }, { "value": "priority", "name": "Mike" } ] } ]
需求
实现按人员姓名过滤的功能:当用户输入姓名(例如“Mike”)时,仅显示包含该用户的分组,且每个分组下只保留匹配的人员条目,示例输出如下:
Group A Mike Group C Mike
当前问题
现有代码仅能实现按分组名称过滤,尝试按姓名过滤的逻辑存在问题,无法得到预期结果。当前处理函数代码:
const handleSearchChange = (e: any) => { if (!e.target.value) return setSearchResults(posts) const resultsArray = posts?.filter((post: any)=> { // return post.label.includes(e.target.value) const result = post.fields.filter((field: any, idx: any) => { return field.name.includes(e.target.value) }) return result }) setSearchResults(resultsArray) }
解决方案
需要同时完成两个操作:筛选出包含目标人员的分组,并且每个分组仅保留匹配的人员条目。修改后的处理函数如下:
const handleSearchChange = (e: any) => { const searchValue = e.target.value.trim().toLowerCase(); // 搜索框为空时恢复原始数据 if (!searchValue) { setSearchResults(posts); return; } const resultsArray = posts?.map(post => { // 过滤当前分组中匹配姓名的人员 const matchedFields = post.fields.filter(field => field.name.toLowerCase().includes(searchValue) ); // 只有当分组存在匹配人员时,才保留该分组并更新其fields return matchedFields.length > 0 ? { ...post, fields: matchedFields } : null; }).filter(Boolean); // 移除无匹配人员的分组 setSearchResults(resultsArray); };
代码说明
- 统一大小写处理:将搜索关键词和人员姓名转为小写,实现不区分大小写的搜索,提升用户体验。
- 分组筛选与字段过滤:
- 用
map遍历每个分组,对分组内的fields进行过滤,得到匹配目标姓名的人员列表。 - 如果分组存在匹配的人员,返回一个新的分组对象(避免修改原数据),替换
fields为匹配列表;否则返回null。
- 用
- 移除无效分组:通过
filter(Boolean)过滤掉没有匹配人员的分组(即null值)。
扩展:同时支持分组名称和人员姓名过滤
如果需要同时支持按分组名称或人员姓名过滤,可修改判断逻辑:
const handleSearchChange = (e: any) => { const searchValue = e.target.value.trim().toLowerCase(); if (!searchValue) { setSearchResults(posts); return; } const resultsArray = posts?.map(post => { const matchedFields = post.fields.filter(field => field.name.toLowerCase().includes(searchValue) ); // 判断分组名称是否匹配 const isGroupMatch = post.label.toLowerCase().includes(searchValue); // 分组名称匹配 或 存在匹配人员时保留分组 if (isGroupMatch || matchedFields.length > 0) { // 分组名称匹配时保留所有人员,否则只保留匹配人员 return isGroupMatch ? post : { ...post, fields: matchedFields }; } return null; }).filter(Boolean); setSearchResults(resultsArray); };
内容的提问来源于stack exchange,提问作者Devmix
相关产品推荐
相关产品推荐

