Ответ от CertainPerformance лучше - проще в реализации и обслуживании, но стоит отметить, что вы также можете сгенерировать регулярное выражение из массива.
Идея достаточно проста - если вы хотите сопоставить r
, re
, rea
, read
, readi
, readin
, reading
, регулярное выражение для этого будет reading|readin|readi|read|rea|re|r
. Причина, по которой вы хотите сначала самый длинный вариант, заключается в том, что в противном случае механизм регулярных выражений остановится при первом совпадении:
let regex = /r|re|rea|read/g
// ↑_________________
console.log( // |
"read".replace(regex, "")// |
// ↑___________________________|
)
Таким образом, вы можете взять слово и выделить его в этом шаблоне, чтобы сгенерировать из него регулярное выражение
function allSubstrings(word) {
let substrings = [];
for (let i = word.length; i > 0; i--) {
let sub = word.slice(0, i);
substrings.push(sub)
}
return substrings;
}
console.log(allSubstrings("reading"))
С этим вы можете просто сгенерировать необходимое регулярное выражение.
function allSubstrings(word) {
let substrings = [];
for (let i = word.length; i > 0; i--) {
let sub = word.slice(0, i);
substrings.push(sub)
}
return substrings;
}
function toPattern(word) {
let substrings = allSubstrings(word);
let pattern = substrings.join("|");
return pattern;
}
console.log(toPattern("reading"))
Последнее, что нужно сделать - это взять массив и преобразовать его в регулярное выражение. Что требует обработки каждого слова и последующего объединения каждого отдельного регулярного выражения в одно, которое соответствует любому из слов:
const array = ['reading', 'books'];
const string = 'If you want to read the book, just read it.';
//generate the pattern
let pattern = array
.map(toPattern) //first, for each word
.join("|"); //join patterns for all words
//convert the pattern to a regex
let regex = new RegExp(pattern, "g");
let result = string.replace(regex, "");
//desiredOutput: 'If you want to the , just it.';
console.log(result);
function allSubstrings(word) {
let substrings = [];
for (let i = word.length; i > 0; i--) {
let sub = word.slice(0, i);
substrings.push(sub)
}
return substrings;
}
function toPattern(word) {
let substrings = allSubstrings(word);
let pattern = substrings.join("|");
return pattern;
}
Итак, как вы можете сгенерировать регулярное выражение из этого массива. В этом случае это работает, но это не гарантируется, потому что есть опасность, что оно может соответствовать тому, что вы не хотите. Например, r
будет соответствовать любому символу, это не обязательно должно быть в слове, которое соответствует этому.
const array = ['reading'];
const string = 'The quick brown fox jumps over the lazy dog';
// ^ ^
let pattern = array
.map(word => allSubstrings(word).join("|"))
.join("|");
let regex = new RegExp(pattern, "g");
let result = string.replace(regex, "");
console.log(result);
function allSubstrings(word) {
let substrings = [];
for (let i = word.length; i > 0; i--) {
let sub = word.slice(0, i);
substrings.push(sub)
}
return substrings;
}
В этот момент все становится сложнее, поскольку вы хотите создать более сложный шаблон для каждого слова. Как правило, вы хотите сопоставить слов , поэтому вы можете использовать символ границы слова \b
, что означает, что шаблон для «чтения» теперь может выглядеть следующим образом:
\breading\b|\breadin\b|\breadi\b|\bread\b|\brea\b|\bre\b|\br\b
↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑ ↑↑
В целях сохранения, по крайней мере, некоторого читаемого результата, его можно вместо этого поместить в группу, и вся группа может быть сделана так, чтобы соответствовать одному слову:
\b(?:reading|readin|readi|read|rea|re|r)\b
↑↑
||____ non-capturing group
Итак, вы должны сгенерировать этот шаблон
function toPattern(word) {
let substrings = allSubstrings(word);
//escape backslashes, because this is a string literal and we need \b as content
let pattern = "\\b(?:" + substrings.join("|") + ")\\b";
return pattern;
}
Что приводит нас к этому
const array = ['reading', 'books'];
const string = 'The quick brown fox jumps over the lazy dog. If you want to read the book, just read it.';
let pattern = array
.map(toPattern)
.join("|");
let regex = new RegExp(pattern, "g");
let result = string.replace(regex, "");
console.log(result);
function allSubstrings(word) {
let substrings = [];
for (let i = word.length; i > 0; i--) {
let sub = word.slice(0, i);
substrings.push(sub)
}
return substrings;
}
function toPattern(word) {
let substrings = allSubstrings(word);
let pattern = "\\b(?:" + substrings.join("|") + ")\\b";
return pattern;
}
Этого будет достаточно для решения вашей задачи. Так что можно сгенерировать регулярное выражение. Последний выглядит так:
/\b(?:reading|readin|readi|read|rea|re|r)\b|\b(?:books|book|boo|bo|b)\b/g
Но большая часть его генерации тратится на генерацию чего-то, что работает . Это не обязательно сложное решение, но, как уже упоминалось, предложенное CertainPerformance лучше, потому что оно проще, что означает меньшую вероятность его сбоя, и его будет проще поддерживать в будущем.