如何检测并移除对象数组中深层嵌套文本的重复项?
问题分析与解决方案
先拆解下你代码里的几个核心问题,这就是为什么重复项没被过滤掉的原因:
误用
map做遍历:Array.map()的设计目的是返回一个新数组,而你只是想用它来执行遍历逻辑。更关键的是,你在回调里的return会直接终止当前的map回调,导致后续的重复检查逻辑根本没机会执行。这里应该用Array.forEach()或者普通for循环来做遍历。重复检查逻辑漏洞:在else分支的for循环里,你只要发现
results里的第一个元素和当前元素标题不匹配,就直接return results.push(each)——这意味着只要第一个元素不重复,不管results后面有没有和当前元素重复的项,都会把当前元素加进去。比如如果results里已经有一个重复项在第二个位置,你的代码完全不会检查到。冗余的条件判断:
!results || !results.length里,results是你初始化的空数组,!results永远是false,只需要判断!results.length就够了。
正确的实现方案
我们可以用Set来记录已经出现过的标题文本,这样检查重复的效率是O(1),逻辑也更清晰:
filterOutDuplicates = (blogIndexContent) => { const arr = blogIndexContent.pages; const results = []; const seenHeadlines = new Set(); arr.forEach(each => { // 用可选链做容错,避免某些对象缺少属性导致报错 const currentHeadline = each?.data?.heading?.[0]?.text; if (!currentHeadline) { // 没有标题的情况,根据需求决定是跳过还是加入结果 results.push(each); return; } // 检查标题是否已存在,不存在则加入结果和Set if (!seenHeadlines.has(currentHeadline)) { seenHeadlines.add(currentHeadline); results.push(each); } }); console.log('Results :', results); return results; }
方案说明
Set的唯一性特性:Set会自动存储不重复的值,我们每次遍历先检查当前标题是否在Set中,不在的话就把标题存入Set,同时把当前对象加入结果数组。- 容错处理:用可选链
?.避免因为某些对象没有data、heading或者heading为空数组时出现报错,让代码更健壮。 - 清晰的遍历逻辑:用
forEach专门做遍历执行逻辑,不会像map那样有返回值的干扰。
如果你的运行环境不支持可选链(比如旧版浏览器),可以换成条件判断的容错方式:
// 单独封装获取标题的函数,做容错处理 const getHeadline = (obj) => { if (obj.data && obj.data.heading && obj.data.heading.length > 0) { return obj.data.heading[0].text; } return null; }; filterOutDuplicates = (blogIndexContent) => { const arr = blogIndexContent.pages; const results = []; const seenHeadlines = new Set(); arr.forEach(each => { const currentHeadline = getHeadline(each); if (!currentHeadline) { results.push(each); return; } if (!seenHeadlines.has(currentHeadline)) { seenHeadlines.add(currentHeadline); results.push(each); } }); console.log('Results :', results); return results; }
内容的提问来源于stack exchange,提问作者Aid19801
相关产品推荐
相关产品推荐

