JavaScript转写脚本如何区分单双字母key 解决map遍历匹配错误问题
解决方法
核心问题
你的现有实现将输入字符串拆分为单个字符逐一匹配,自然无法识别长度大于1的组合键,导致双字母组合被拆分为两个单字符分别转写。
核心逻辑
要实现正确匹配,必须遵循长键优先匹配的原则,先尝试匹配更长的组合,再匹配短键,避免短键提前消耗字符导致长组合匹配失败。
方案1:正则替换实现(简洁通用)
function transliterate(word){ const translitMap = { /*...*/'g':'\u{1050A}','gj':'\u{1050B}','h':'\u{1050C}','i':'\u{1050D}','j':'\u{1050E}'/*...*/ }; // 所有键按长度降序排序,保证长组合优先被匹配 const sortedKeys = Object.keys(translitMap).sort((a, b) => b.length - a.length); // 生成正则,自动转义键中的正则特殊字符(如果你的键没有特殊字符可省略转义步骤) const matchRegex = new RegExp( sortedKeys.map(key => key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'g' ); // 匹配后替换为对应转写结果 return word.replace(matchRegex, match => translitMap[match]); }
方案2:手动遍历实现(可控性更高)
如果需要自定义更复杂的匹配规则,可以用手动遍历的方式实现:
function transliterate(word) { const translitMap = { /*...*/'g':'\u{1050A}','gj':'\u{1050B}','h':'\u{1050C}','i':'\u{1050D}','j':'\u{1050E}'/*...*/ }; // 先拿到最长的键长度,作为匹配的最大尝试长度 const maxKeyLen = Math.max(...Object.keys(translitMap).map(k => k.length)); let result = ''; let index = 0; while (index < word.length) { let isMatched = false; // 从最长长度开始尝试匹配 for (let len = maxKeyLen; len >= 1; len--) { if (index + len > word.length) continue; const currentSlice = word.slice(index, index + len); if (translitMap.hasOwnProperty(currentSlice)) { result += translitMap[currentSlice]; index += len; isMatched = true; break; } } // 无匹配的字符原样保留 if (!isMatched) { result += word[index]; index += 1; } } return result; }
两种方案输入gj时都会返回预期的\u{1050B},不会拆分为两个单字符匹配。
内容的提问来源于stack exchange,提问作者gjelbrim
相关产品推荐
相关产品推荐

