基于1的单次/双次出现分割含1、2的字符串(需匹配指定顺序)
解决按特定规则拆分1/2字符串的问题
你遇到的核心问题是正则表达式的匹配优先级——当你使用/1{2}|2|1{1}/g时,正则引擎会优先匹配更长的1{2}模式,导致连续的1会先被拆成双数,完全不符合你需要的拆分顺序(尤其是当连续1的长度为奇数时)。
下面提供两种可行的解决方案:
方案1:分段处理(直观易维护)
这种方法先将字符串拆分为连续的1段和2段,再分别按规则处理,逻辑清晰,后续调整规则也更方便:
function splitTargetStr(str) { // 分割为连续的1或2组成的片段 const segments = str.match(/1+|2+/g) || []; const finalResult = []; segments.forEach(segment => { if (segment.startsWith('2')) { // 所有2单独拆分 finalResult.push(...segment.split('')); } else { const length = segment.length; if (length % 2 === 1) { // 奇数个1:先添加1个单个1,剩余部分拆为11 finalResult.push('1'); const pairCount = (length - 1) / 2; for (let i = 0; i < pairCount; i++) { finalResult.push('11'); } } else { // 偶数个1:直接拆为若干个11 const pairCount = length / 2; for (let i = 0; i < pairCount; i++) { finalResult.push('11'); } } } }); return finalResult; } // 测试验证 console.log(splitTargetStr("111221")); // 输出: ["1","11","2","2","1"] console.log(splitTargetStr("11111")); // 输出: ["1","11","11"] console.log(splitTargetStr("111111")); // 输出: ["11","11","11"] console.log(splitTargetStr("21211")); // 输出: ["2","1","2","11"]
方案2:纯正则表达式(简洁高效)
通过正向预查控制匹配顺序,确保单个1仅在后续剩余1的数量为偶数时才被匹配,否则匹配11:
const splitRegex = /(1(?=(1{2})*([^1]|$)))|11|2/g; // 测试验证 console.log("111221".match(splitRegex)); // 输出: ["1","11","2","2","1"] console.log("11111".match(splitRegex)); // 输出: ["1","11","11"] console.log("111111".match(splitRegex)); // 输出: ["11","11","11"] console.log("2112".match(splitRegex)); // 输出: ["2","11","2"]
正则逻辑解释:
1(?=(1{2})*([^1]|$)):匹配单个1,且该1之后的所有1的总数为偶数(包括0个),直到遇到非1字符或字符串结尾。这保证了单个1后面的1能完全拆成双数的11。11:当单个1的匹配条件不满足时(比如当前位置开始的1数量为奇数,但前面已无符合条件的单个1),匹配两个1。2:直接匹配单个2,完成拆分。
方案对比
- 分段处理:可读性强,规则调整灵活,适合需要后续修改拆分逻辑的场景。
- 纯正则:代码简洁,执行效率高,但可读性稍弱,适合拆分规则固定的场景。
内容的提问来源于stack exchange,提问作者user10109
相关产品推荐
相关产品推荐

