Regex для добавления строки в начало каждого слова в зависимости от условия - PullRequest
1 голос
/ 23 февраля 2020

У меня есть строка, которая выглядит следующим образом

someString = "#3Hello there! How many #4candies did you sell today? Do have any #4candies left?"

lookupDict = {"Hello there": "#3", "candies": "#4"}

Теперь я хочу заменить все термины в строке someString на #0, которых нет в словаре lookupDict. Я не могу разделить на пробел " ", так как это приведет к тому, что некоторые термины, такие как Hello there, будут отображаться как два разных слова Hello и there, и это никогда не будет соответствовать моему состоянию.

Теперь я знаю применить регулярное выражение basi c, которое добавит #0 перед каждым словом. Например, что-то вроде

let regex = /(\b\w+\b)/g;

someString = someString.replace(regex, '#0$1'));

Но это слепо добавит #0 к каждому термину и не будет искать в словаре lookupDict.

Есть ли способ объединить регулярное выражение с поиском в словаре и назначить #0 соответственно? По сути, конечный результат будет выглядеть примерно так:

someString = "#3Hello there! #0How #0many #4candies #0did #0you #0sell #0today? #0Do #0have #0any #4candies #0left?"

Примечание. Пробелы здесь можно рассматривать как границы слов.

Ответы [ 3 ]

1 голос
/ 23 февраля 2020

Таким образом, можно не беспокоиться о длине ключа lookupDict или о чем-либо еще:

let someString =
  "#3Hello there! How many #4candies did you sell today? #3Hello there! Do have any #4candies left?#3Hello there! #7John Doe! some other text with having #7John Doe person again";

const lookupDict = { "Hello there": "#3", candies: "#4", "John Doe": "#7" };

Object.keys(lookupDict).map((key, i) => {
  const regex = new RegExp(key, "g");
  someString = someString.replace(regex, lookupDict[key]); // replace each key to the value: Hello world => #3
});

someString = someString.replace(/ /gi, " #0"); // replace each space

Object.keys(lookupDict).map((key, i) => {
  const regex = new RegExp(lookupDict[key] + lookupDict[key], "g");
  someString = someString.replace(regex, `${lookupDict[key]}${key}`); // role back the value to key+value
});

someString = someString.replace(/#0#/gi, "#"); // replace #0 for each lookupDict key value

console.log(someString, '<TheResult/>');
1 голос
/ 23 февраля 2020

Вы можете использовать следующие логи c:

  • Создать массив подстрок, которые нужно пропустить, которые объединены value с и key с ассоциативного массива
  • Сортировка элементов по длине в порядке убывания, поскольку границы слов могут не работать с фразами, содержащими пробелы
  • Скомпилировать шаблон регулярного выражения, который будет состоять из двух альтернатив: первый будет соответствовать элементам массива (экранированный для использования в шаблоне регулярных выражений), заключенный в группу захвата, а другая будет соответствовать остальным «словам»
  • Когда совпадение найдено, проверьте, соответствует ли группа 1. Если группа 1 соответствует, просто верните значение соответствия, иначе добавьте #0 к значению соответствия.

Вот реализация:

let someString = "#3Hello there! How many #4candies did you sell today? Do have any #4candies left? #0how #0much";
const lookupDict = {"Hello there": "#3", "candies": "#4", "how": "#0", "much": "#0"};
let patternDict = [];                             // Substrings to skip
for (var key in lookupDict) {                     
  patternDict.push( `${lookupDict[key]}${key}` ); // Values + keys
}
patternDict.sort(function(a, b){                  // Sorting by length, descending
  return b.length - a.length;
});
var rx = new RegExp("(?:^|\\W)(" + patternDict.map(function(m) { // Building the final pattern
    return m.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');}
  ).join("|") + ")(?!\\w)|\\S+", "gi");
// rx = /(?:^|\W)(#3Hello there|#4candies|#0much|#0how)(?!\w)|\S+/gi
someString = someString.replace(rx, (x, y) => y ? x : `#0${x}` );
console.log(someString);
// => #3Hello there! #0How #0many #4candies #0did #0you #0sell #0today? #0Do #0have #0any #4candies #0left? #0how #0much

Регулярное выражение будет выглядеть следующим образом:

/(?:^|\W)(#3Hello there|#4candies|#0much|#0how)(?!\w)|\S+/gi

См. Демонстрационное регулярное выражение (опция PHP выбрана, чтобы выделить зеленые группы) .

Подробности

  • (?:^|\W) - группа без захвата, соответствующая либо началу строки (^), либо (|) любому -word char (= символ, отличный от буквы ASCII, di git или _)
  • (#3Hello there|#4candies|#0much|#0how) - Захват группы 1, совпадающей с любым из lookupDict составных значений + ключей
  • (?!\w) - отрицательный прогноз, который не соответствует совпадению, если непосредственно справа от текущего местоположения есть слово char
  • | - или
  • \S+ - 1+ непробельные символы.
0 голосов
/ 23 февраля 2020

Вы можете передать функцию в .replace в качестве второго параметра и проверить соответствующий токен в словаре

Я изменил регулярное выражение, чтобы не включать # в результаты

Hello there проблематично c, как долго может длиться один семестр? максимум 2 слова?

someString = "#3Hello there! How many #4candies did you sell today? Do have any #4candies left?"

let regex = /(?<!#)(\b\w+\b)/g;

someString = someString.replace(regex, x => {
// check x in dict
	return `#0${x}`
});
console.log(someString)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...