Найти и заменить по словарю, используя ключи только один раз - PullRequest
1 голос
/ 29 декабря 2011

Это продолжение Поиск нескольких ключевых слов в словаре .

Мои вопросы ...

  1. Первое: я считаю, что это соответствует словам, которые не являются целыми.Например, если в моем словаре есть слово short, оно соответствует слову short.Как бы мне это остановить?

  2. И второе не так важно, но было бы неплохо: как бы мне было сделать так, чтобы оно совпадало только один раз для контента?Так что короткий не определяется дважды в одной и той же области содержимого.

Спасибо!

1 Ответ

5 голосов
/ 30 декабря 2011

Я выполнил следующие дополнительные требования:

  • Не соответствует shortly при поиске short (потому что shortly - это другое слово)
  • Используйте ключи в словаре только один раз.
    Пример ввода: ключ = foo, замена = bar, содержимое = foo foo.
    Выход: bar foo (заменяется только первый foo).

Демо: http://jsfiddle.net/bhGE3/3/

Использование:

  1. Определить dictionary. Каждый ключ будет использоваться только один раз.
  2. Определить content. На основе этой строки будет создана новая строка.
  3. Опционально , определите функцию replacehandler. Эта функция вызывается при каждом совпадении. Возвращаемое значение будет использоваться для замены совпавшей фразы.
    По умолчанию replacehandler вернет соответствующую словарную фразу. Функция должна принимать два аргумента: key и dictionary.
  4. Звоните replaceOnceUsingDictionary(dictionary, content, replacehandler)
  5. Обработать вывод, например. показать content пользователю.

Код:

var dictionary = {
    "history": "war . ",
    "no": "in a",
    "nothing": "",
    "oops": "",
    "time": "while",
    "there": "We",
    "upon": "in",
    "was": "get involved"
};
var content = "Once upon a time... There was no history. Nothing. Oops";
content = replaceOnceUsingDictionary(dictionary, content, function(key, dictionary){
    return '_' + dictionary[key] + '_';
});
alert(content);
// End of implementation

/*
* @name        replaceOnceUsingDictionary
* @author      Rob W http://stackoverflow.com/users/938089/rob-w
* @description Replaces phrases in a string, based on keys in a given dictionary.
*               Each key is used only once, and the replacements are case-insensitive
* @param       Object dictionary  {key: phrase, ...}
* @param       String content
* @param       Function replacehandler
* @returns     Modified string
*/
function replaceOnceUsingDictionary(dictionary, content, replacehandler) {
    if (typeof replacehandler != "function") {
        // Default replacehandler function.
        replacehandler = function(key, dictionary){
            return dictionary[key];
        }
    }

    var patterns = [], // \b is used to mark boundaries "foo" doesn't match food
        patternHash = {},
        oldkey, key, index = 0,
        output = [];
    for (key in dictionary) {
        // Case-insensitivity:
        key = (oldkey = key).toLowerCase();
        dictionary[key] = dictionary[oldkey];

        // Sanitize the key, and push it in the list
        patterns.push('\\b(?:' + key.replace(/([[^$.|?*+(){}])/g, '\\$1') + ')\\b');

        // Add entry to hash variable, for an optimized backtracking at the next loop
        patternHash[key] = index++;
    }
    var pattern = new RegExp(patterns.join('|'), 'gi'),
        lastIndex = 0;

    // We should actually test using !== null, but for foolproofness,
    //  we also reject empty strings
    while (key = pattern.exec(content)) {
        // Case-insensitivity
        key = key[0].toLowerCase();

        // Add to output buffer
        output.push(content.substring(lastIndex, pattern.lastIndex - key.length));
        // The next line is the actual replacement method
        output.push(replacehandler(key, dictionary));

        // Update lastIndex variable
        lastIndex = pattern.lastIndex;

        // Don't match again by removing the matched word, create new pattern
        patterns[patternHash[key]] = '^';
        pattern = new RegExp(patterns.join('|'), 'gi');

        // IMPORTANT: Update lastIndex property. Otherwise, enjoy an infinite loop
        pattern.lastIndex = lastIndex;
    }
    output.push(content.substring(lastIndex, content.length));
    return output.join('');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...