如何根据搜索词筛选JavaScript嵌套对象数组并保留匹配子对象?
嵌套对象数组筛选:保留父对象并过滤子数组匹配项
问题场景
现有嵌套对象数组数据,使用filter+some仅能筛选出包含匹配子对象的父对象,但无法将父对象的links数组过滤为仅含匹配项。需要实现:当搜索词为"account"时,返回仅保留匹配子对象的嵌套数组结果。
原始代码
const contents = [ { title: "Accounts", links: [ { header: "Accounts by Status", }, ], }, { title: "Executions", links: [ { header: "Purchase and Sales", }, { header: "AMLA Transactions Proof List", }, { header: "Account Ranking", }, { header: "Trading Summary", }, ], }, ]; const search = "account"; console.log( contents.filter((content) => content.links.some((link) => link.header.toLowerCase().includes(search.toLowerCase()) ) ) );
期望输出
[{ title: 'Accounts', links: [{ header: 'Accounts by Status' }] }, { title: 'Executions', links: [{ header: 'Account Ranking' }] } ]
解决方案
方法1:filter + map 分步处理
先筛选出符合条件的父对象,再对每个父对象的links数组做过滤,生成新对象:
const contents = [ { title: "Accounts", links: [ { header: "Accounts by Status", }, ], }, { title: "Executions", links: [ { header: "Purchase and Sales", }, { header: "AMLA Transactions Proof List", }, { header: "Account Ranking", }, { header: "Trading Summary", }, ], }, ]; const search = "account"; const lowerSearch = search.toLowerCase(); // 提前转小写,避免重复转换 const result = contents // 第一步:筛选出包含匹配links的父对象 .filter(content => content.links.some(link => link.header.toLowerCase().includes(lowerSearch) ) ) // 第二步:对每个父对象,替换links为过滤后的数组 .map(content => ({ ...content, // 保留原对象的其他属性 links: content.links.filter(link => link.header.toLowerCase().includes(lowerSearch) ) })); console.log(result);
方法2:reduce 一次遍历完成(更高效)
使用reduce合并筛选和过滤操作,只遍历原数组一次,性能更优:
const contents = [ { title: "Accounts", links: [ { header: "Accounts by Status", }, ], }, { title: "Executions", links: [ { header: "Purchase and Sales", }, { header: "AMLA Transactions Proof List", }, { header: "Account Ranking", }, { header: "Trading Summary", }, ], }, ]; const search = "account"; const lowerSearch = search.toLowerCase(); const result = contents.reduce((acc, content) => { // 过滤当前父对象中匹配的links const matchedLinks = content.links.filter(link => link.header.toLowerCase().includes(lowerSearch) ); // 如果有匹配的子项,就把新对象加入结果数组 if (matchedLinks.length > 0) { acc.push({ ...content, links: matchedLinks }); } return acc; }, []); console.log(result);
说明
- 提前将搜索词转小写,避免在多次判断中重复转换,提升性能。
- 使用对象展开运算符
...content保留原对象的所有其他属性,确保不会丢失数据。 - 两种方法都能得到期望的输出,
reduce方法减少了一次数组遍历,适合处理大量数据的场景。
内容的提问来源于stack exchange,提问作者Pau Pang
相关产品推荐
相关产品推荐

