You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript:用.filter()获取去重后的重复字母及替代方案

问题

我想用.filter()从字符串里提取重复的字母组成新数组,但希望每个重复字母只出现一次,不管它重复多少次。我写的代码如下:

const fullName = "Muhammad Ali";
const fullNameLowercase = fullName.toLowerCase();
const splitName = fullNameLowercase.split("");

let repeats = splitName.filter((letter, index) => {return splitName.indexOf(letter) !== index});
console.log(repeats); // 输出 [ 'm', 'm', 'a', 'a' ]

现在输出的数组里重复字母出现了多次,怎么改才能让每个重复字母只留一次?另外有没有不用.filter()的更高效办法?


用.filter()的改进实现

你原来的代码会把每一次重复出现的字符都保留下来,要实现去重,可以在过滤逻辑里加个判断:只保留第一次被检测到重复的那个字符,或者用一个集合记录已经加入结果的字符。

方案1:利用lastIndexOf判断

const fullName = "Muhammad Ali";
const fullNameLowercase = fullName.toLowerCase();
const splitName = fullNameLowercase.split("");

let repeats = splitName.filter((letter, index) => {
  // 当前字符不是第一次出现,且是最后一次出现的位置——这样就能只保留最后一个重复项
  return splitName.indexOf(letter) !== index && splitName.lastIndexOf(letter) === index;
});
console.log(repeats); // 输出 [ 'm', 'a' ]

方案2:用Set记录已添加的字符

const fullName = "Muhammad Ali";
const fullNameLowercase = fullName.toLowerCase();
const splitName = fullNameLowercase.split("");

const seen = new Set();
const repeats = splitName.filter((letter) => {
  // 先判断这个字符是否是重复的(出现次数大于1)
  const isDuplicate = splitName.indexOf(letter) !== splitName.lastIndexOf(letter);
  // 如果是重复字符且没被记录过,就加入结果并标记为已见过
  if (isDuplicate && !seen.has(letter)) {
    seen.add(letter);
    return true;
  }
  return false;
});
console.log(repeats); // 输出 [ 'm', 'a' ]

更高效的非.filter()实现

原方法里多次调用indexOf和lastIndexOf,每次都是遍历整个数组,时间复杂度是O(n²),处理长字符串时效率很低。可以用一次遍历统计字符出现次数,再筛选出次数大于1的字符,时间复杂度能降到O(n)。

用普通对象统计次数

const fullName = "Muhammad Ali";
const fullNameLowercase = fullName.toLowerCase();
const countMap = {};

// 第一次遍历,统计每个字符出现的次数
for (const letter of fullNameLowercase) {
  countMap[letter] = (countMap[letter] || 0) + 1;
}

// 提取出现次数大于1的字符
const repeats = Object.keys(countMap).filter(letter => countMap[letter] > 1);
console.log(repeats); // 输出 [ 'm', 'a' ]

用Map统计次数

const fullName = "Muhammad Ali";
const fullNameLowercase = fullName.toLowerCase();
const countMap = new Map();

// 统计字符出现次数
for (const letter of fullNameLowercase) {
  countMap.set(letter, (countMap.get(letter) || 0) + 1);
}

// 筛选重复字符
const repeats = [];
for (const [letter, count] of countMap) {
  if (count > 1) {
    repeats.push(letter);
  }
}
console.log(repeats); // 输出 [ 'm', 'a' ]

内容的提问来源于stack exchange,提问作者claramarsango

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:00:59