Skip to content

匹配字符串中的重复子串 ​

在前端开发中,我们经常需要处理字符串中重复子串的匹配问题。本文将介绍两种常用的解决方案,并深入探讨正则表达式在字符串匹配中的应用。

方案一:使用字符串原生方法 ​

这种方法通过遍历字符串并使用slice()方法来检查重复子串:

js
let flag = true
for (let i = 0; i < line.length - 3; i++) {
    // 获取长度为3的子串
    let left = line.slice(i, i + 3);
    // 使用lastIndexOf检查是否存在重复
    if (line.lastIndexOf(left) > i) {     
        flag = false;
        break;
    }
}

原理解析:

  • 通过slice()截取固定长度的子串
  • 使用lastIndexOf()查找该子串最后出现的位置
  • 如果最后出现的位置大于当前位置,说明存在重复

方案二:使用正则表达式 ​

正则表达式提供了更简洁的解决方案:

js
// 匹配任意重复的3个或更多字符
/(.{3,}).*\1/g.test(str)

正则表达式详解:

  • (.{3,}) - 捕获组,匹配3个或更多任意字符
  • .* - 匹配任意数量的任意字符
  • \1 - 反向引用,表示与第一个捕获组相同的内容
  • g - 全局匹配标志

正则表达式进阶应用 ​

1. 匹配连续重复字符 ​

js
const str = "aabb..ccee!!!";
const reg = /(.)\1+/ig;

// 获取所有重复字符
const matches = str.match(reg);     // ["aa", "bb", "..", "cc", "ee", "!!!"]

// 去重复,保留单个字符
const unique = str.replace(reg, "$1");  // "ab.ce!"

说明:

  • (.) 捕获任意单个字符
  • \1+ 表示之前捕获的字符重复一次或多次
  • $1 在替换时引用第一个捕获组

2. 匹配"ABBB"模式 ​

js
const str = "AbbbCdd+!!";
const reg = /(.)(?!\1)(.)\2+/ig;

// 匹配结果
const matches = str.match(reg);  // ["Abbb", "Cdd", "+!!"]

模式解析:

  • (.) 匹配第一个字符(A)
  • (?!\1) 否定向前查找,确保第二个字符与第一个不同
  • (.)\2+ 匹配第二个字符(B)及其重复

3. 验证不重复字符 ​

js
const str = "123465";
const reg = /^(?!\d*?(\d)\d*?\1)\d{6}$/gi;

// 验证6位数字是否存在重复
console.log(reg.test(str));  // true

正则说明:

  • ^ 和 $ 确保匹配整个字符串
  • (?!\d*?(\d)\d*?\1) 否定向前查找,确保不存在重复数字
  • \d{6} 要求正好6位数字

实践建议 ​

  1. 对于简单的重复检查,字符串方法更直观易懂
  2. 需要复杂模式匹配时,正则表达式效率更高
  3. 在处理大量数据时,建议先进行性能测试再选择合适方案

参考资料 ​