如何使用高阶函数找出数组中出现多次的作者?含array.filter用法疑问
嘿,刚好我之前也折腾过类似的需求,你选Array.filter确实找对方向了,但光靠它还不够,得搭配其他高阶函数先统计每个作者的出现次数,这样才能精准筛选出重复项。我分两种场景给你一步步拆解:
1. 处理对象数组的情况
假设你的对象数组长这样(比如每一项是带作者信息的书籍对象):
const books = [ { title: '《前端进阶指南》', author: 'Alice' }, { title: '《JS高阶技巧》', author: 'Alice' }, { title: '《CSS实战秘籍》', author: 'Bob' }, { title: '《Node.js实战》', author: 'Charlie' }, { title: '《React进阶》', author: 'Bob' } ];
步骤1:先统计每个作者的出现次数
用Array.reduce来生成一个统计对象,键是作者名,值是对应出现次数:
const authorCount = books.reduce((countMap, book) => { // 如果当前作者还没在统计表里,默认次数为0,再加1 countMap[book.author] = (countMap[book.author] || 0) + 1; return countMap; }, {}); // 结果会是:{ Alice: 2, Bob: 2, Charlie: 1 }
步骤2:用filter筛选重复作者,同时去重
直接用filter会把所有重复的项都返回(比如Alice会出现两次),所以我们要搭配Set来确保只保留唯一的重复作者:
const seen = new Set(); const duplicateAuthors = books.filter(book => { // 判断当前作者的出现次数是否大于1 const isDuplicate = authorCount[book.author] > 1; // 如果是重复项且还没被加入Set,就标记为需要保留,并加入Set避免重复 if (isDuplicate && !seen.has(book.author)) { seen.add(book.author); return true; } return false; // 最后用map提取出作者名数组 }).map(book => book.author); // 最终结果:['Alice', 'Bob']
2. 处理普通作者数组的情况
如果你的数组就是单纯的作者名字符串数组,比如:
const authors = ['Alice', 'Alice', 'Bob', 'Charlie', 'Bob', 'David'];
方法一:和对象数组逻辑一致(先统计再筛选)
同样用reduce统计次数,再用filter+Set去重:
const authorCount = authors.reduce((countMap, author) => { countMap[author] = (countMap[author] || 0) + 1; return countMap; }, {}); const seen = new Set(); const duplicateAuthors = authors.filter(author => { const isDuplicate = authorCount[author] > 1; if (isDuplicate && !seen.has(author)) { seen.add(author); return true; } return false; }); // 结果:['Alice', 'Bob']
方法二:更简洁的写法(不用提前统计)
利用indexOf和lastIndexOf的特性:如果一个元素的首次出现位置和最后出现位置不一样,说明它出现了不止一次。再用Set去重:
const duplicateAuthors = [...new Set( authors.filter(author => authors.indexOf(author) !== authors.lastIndexOf(author)) )]; // 结果同样是:['Alice', 'Bob']
不过这个方法要注意,如果数组很大,性能会比第一种差一点,因为indexOf和lastIndexOf每次都会遍历整个数组。小数据量的话完全没问题,写法更清爽。
内容的提问来源于stack exchange,提问作者Admir Husić
相关产品推荐
相关产品推荐

