Для данного текста в ASCII или Unicode, я должен заменить жетоны слов на границы слов заменой.Мой подход состоял в том, чтобы искать токен с помощью регулярного выражения, которое учитывает Unicode и не-Unicode регистр - см. здесь , а затем сопоставлять вхождение этого токена итерацию по RegExp.exec
.отслеживая последний увиденный токен:
/**
* Replace tokens in text
* It support both Unicode and ASCII Regex for word boundaries
* @param {*} isUnicode true to use Unicode Regex
* @param {*} text input text
* @param {*} tokens Tokens indexes
* @param {*} words Words
* @param {*} expr Replacement
*/
var replaceTokens = function (isUnicode, text, tokens, words, expr) {
const seen = new Map();
var pattern = "\\b($1)\\b";
if (isUnicode) pattern = "(?<!\\S)$1(?!\\S)";
tokens.forEach((token, index) => {
var word = words[index];
var escaped = word.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
var wordRegex = new RegExp(pattern.replace('$1', escaped), "g");
var match = null;
while ((match = wordRegex.exec(text)) !== null) {
if (match.index > (seen.get(word) || -1)) {
var wordEnd = match.index + word.length - 1;
var replacement = expr[token].replace('$1', escaped);
text = text.slice(0, match.index) + replacement + text.slice(wordRegex.lastIndex);
seen.set(word, wordEnd);
break;
}
}
});
return text;
}//replaceTokens
Поэтому для его использования мне нужен исходный текст в text
, массив words
, массив tokens
слов индексов,карта expr
замен, например
text = "Hello Word"
words = ["Hello", "Word"]
tokens = ["1", "2"]
expr = { "1" : "<span style="color:blue;">$1</span>", "2": "<span style="color:red;">$1</span>"}
replaceTokens(false, text, tokens, words, expr)
или в случае Unicode:
text = "तुम मुझे दोस्त कहते कहते हो"
words = ["तुम","मुझे","दोस्त","कहते","कहते","हो"]
//...tokens and expr index
replaceTokens(true, text, tokens, words, expr)
Я не уверен, что это оптимальное решение из-за вложенных операций.Я попытался использовать String.replace
и указать функцию для замены - см. здесь вместо использования вложенного RegExp.exec
, но я не смог понять, как это сделать.В более простом решении мне понравилось
text = text.replace(new RegExp("\\b(" + word + ")\\b", "gi"), expr[token]);
, но этот подход не учитывает повторение слова в нескольких позициях (он заменяет все), поэтому он не работает должным образом, даже если он был более вычислительнымэффективный.