如何用JavaScript保留掩码格式移除两字符串非共有数字字符
需求说明
现有两个字符串:
- 可动态变化的格式掩码字符串
- 用户输入的原始字符串
需要实现的逻辑:保留掩码的原有格式,移除两个字符串中不共有的数字字符。掩码中未被用户输入覆盖的占位数字需要全部移除。
示例输入
rawValue: "25155122" // 用户输入原始串 value: "2 5155 1220 0000" // 格式掩码串
期望输出
newValue = "2 5155 122"
结果中的0属于掩码占位字符,用户尚未输入后续对应数字,因此需要被移除。
原有实现问题
基于Set差集的实现存在本质逻辑缺陷:
Set结构会自动对字符去重,丢失数字的出现顺序和重复计数,无法按位置匹配对应字符- 没有区分掩码中的格式字符(如空格、分隔符)和数字占位符,会误删需要保留的格式内容
- 集合差集逻辑无法处理「用户输入长度短于掩码占位长度」的截断场景,无法识别需要移除的末尾占位符
原有错误代码如下:
const strSet = str => new Set(str.split('')); const setDiff = (a, b) => new Set(Array.from(a).filter(item => !b.has(item))); const prune = (str, set) => str.split('').filter(x => set.has(x)) .join(''); const diff = setDiff(strSet(rawValue), strSet(value)); const a1 = prune(value, diff); const b1 = prune(rawValue, diff);
正确实现方案
核心思路
用指针按顺序匹配用户输入的数字,遍历掩码时保留有效范围内的格式字符,把掩码的数字位置匹配为用户输入的数字,用户输入耗尽后直接截断后续所有掩码内容:
- 先提取用户输入
rawValue中的所有数字序列,记录总长度 - 初始化数字匹配指针为0,结果数组为空
- 逐字符遍历掩码字符串
value:- 如果当前字符不是数字,且指针还没走完用户输入的数字序列,就把这个格式字符加入结果
- 如果当前字符是数字:
- 若指针已经走到用户数字序列末尾,直接终止遍历(后面都是占位内容,不需要保留)
- 若指针未到末尾,把用户数字序列中指针位置的字符加入结果,指针右移一位
- 遍历结束后拼接结果数组返回即可
可运行代码
function formatWithMask(rawValue, maskValue) { // 提取用户输入的所有数字,自动忽略非数字内容 const inputDigits = rawValue.replace(/\D/g, '').split(''); let digitIndex = 0; const result = []; for (const char of maskValue) { // 非数字为格式分隔符,在有效输入范围内就保留 if (/\D/.test(char)) { if (digitIndex < inputDigits.length) { result.push(char); } continue; } // 遇到数字位,先判断用户输入是否已经全部匹配完成 if (digitIndex >= inputDigits.length) { break; } // 填入对应位置的用户输入数字,指针后移 result.push(inputDigits[digitIndex]); digitIndex++; } return result.join(''); } // 测试示例 const rawValue = "25155122"; const value = "2 5155 1220 0000"; const newValue = formatWithMask(rawValue, value); console.log(newValue); // 输出 "2 5155 122",符合预期
方案适配性
这个实现支持任意动态格式掩码,不管掩码用空格、横杠、括号作为分隔符都能正确保留格式,同时自动截断用户未输入部分的占位符,不会出现Set方案去重、顺序错乱的问题。
内容的提问来源于stack exchange,提问作者karterkortland
相关产品推荐
相关产品推荐

