
本文介绍一种使用 set 去重机制避免重复匹配的优雅方案,解决嵌套 for 循环导致的字母重复输出问题,适用于多单词数组与目标字符串的公共字符提取场景。
本文介绍一种使用 set 去重机制避免重复匹配的优雅方案,解决嵌套 for 循环导致的字母重复输出问题,适用于多单词数组与目标字符串的公共字符提取场景。
在字符串比对任务中,若直接用双重 for 循环逐字符遍历(如遍历水果名中的每个字母再与目标字符串逐个比对),极易因重复字母触发多次匹配——例如 "Apple" 中的 'p' 出现两次,而 "apple" 中也有 'p',就会被匹配两次,最终导致结果膨胀(如 'aaa' → 'aaaaaa')。根本症结在于:未对源字符串的字符集合做去重预处理,也未控制“一个字母只匹配一次”这一语义。
正确解法应聚焦于「字母集合交集」而非「字符位置配对」。推荐使用 Set 数据结构天然的唯一性特性:
- 首先将目标字符串转为小写并构建成
Set,自动剔除重复字母(如"apple"→Set {'a','p','l','e'}); - 对数组中每个单词,同样转小写后取唯一字符(
[...new Set(fruit.toLowerCase())]),再用filter()筛选哪些字符存在于目标 Set 中; - 最后将每组匹配结果拼接为字符串,形成对应单词的公共字母串。
以下是可直接运行的完整实现:
const fruits = ["Banana", "Orange", "Apple", "Mango", "Apple"];
let myString = "apple";
const findCommonLetters = (array, string) => {
const uniqueStringLetters = new Set(string.toLowerCase()); // ✅ 目标字符串去重
return array.map(fruit =>
[...new Set(fruit.toLowerCase())] // ✅ 单词内字母去重
.filter(letter => uniqueStringLetters.has(letter)) // ✅ 高效 O(1) 查找
.join('')
);
};
console.log(findCommonLetters(fruits, myString));
// 输出: ['aepl', '', 'aepl', '', 'aepl']
// 解释: "Banana"→'a','e','p','l';"Orange"无共同字母→空串;其余"Apple"同理⚠️ 注意事项:
-
indexOf()在原代码中误用于单个字符(myString[j].indexOf(...)),但myString[j]是字符串(长度为1),应直接比较===或用includes(); -
return myString(j)语法错误(应为return myString[j]),且提前return会终止整个函数,无法处理全部字符; - 若需全局所有公共字母(而非每个单词单独计算),可将结果扁平化后再次去重:
[...new Set(matches.flat().join(''))].join(''); - 大小写敏感性需统一处理(如全部
.toLowerCase()),避免'A'与'a'被视为不同字符。
该方法时间复杂度优化至 O(n + m)(n 为数组总字符数,m 为目标字符串长度),远优于嵌套循环的 O(n × m),兼具可读性、健壮性与性能优势。

















