首页 文章

JS突出显示匹配的内容x次

提问于
浏览
4

如何突出显示x次出现

如何仅在纯JS中突出显示来自一组文本的匹配的有限子集,以便每个匹配仅出现x个高亮显示 .

var matches = new Array('fox', 'dog');
var MaxHighlights = 2;

原创内容

快速的棕色狐狸跳过懒狗,但懒狗很快就 grab 了棕色的狐狸 . 一般来说,狐狸与狗不是很好的匹配 .

突出显示的内容

快速的棕色 fox 跳过懒惰的 dog 但懒惰的 dog 很快就能 grab 棕色 fox . 一般来说,狐狸与狗不是很好的匹配 .


对于额外的积分,我最好只突出每个句子一个匹配 .

首选突出显示的内容

快速的棕色 fox 跳过懒惰的 dog 但懒惰的狗很快就 grab 了棕色的狐狸 . 一般来说 foxdog 不是很好的匹配 .

我正在使用它是我突出显示尝试的基础http://www.the-art-of-web.com/javascript/search-highlight

2 回答

  • 2

    我的解决方案使用replace()word-boundaries模式和global modifier g .

    replace is, that a callback function can be passed as replacement 的优点 . 我希望你喜欢它,发现它非常有趣,因为JS还没有做太多 . 所以纠正任何错误,如果你找到请:)

    // test it
    var WordsToMatch = new Array('fox', 'dog');
    
    var MaxHighlights = 2;  // no limit = 0
    
    var TestStr = 
    'The quick brown fox jumps over the lazy dog but the lazy dog is '+
    'quick of the mark to catch the brown fox. In general the ' +
    'fox versus the dog is not a good match.';
    
    document.write(highlight(TestStr, WordsToMatch, MaxHighlights));
    
    // --- JOHNNY 5's WORD HIGHLIGHTER ---
    
    // highlight words in str using a callback function
    function highlight (str, words, limit)
    {
      for(var i = 0; i < words.length; i++)
      {
        // match each word case insensitive using word-boundaries
        var pattern = new RegExp("\\b" + words[i] + "\\b","gi");
    
        var j = 0;
        str = str.replace(pattern, function (w) {
          j++; return ((limit <= 0) || (j <= limit)) ? "<b>" + w + "</b>" : w;
        });
      }
    
      return str;
    }
    

    回调函数将返回突出显示的匹配作为替换,直到达到限制 .

    输出:

    快速的棕色狐狸跳过懒狗,但懒狗很快就 grab 了棕色的狐狸 . 一般来说,狐狸与狗不是很好的匹配 .


    EDIT :现在我明白了,还有额外的积分......

    对于额外的积分,我最好只突出每个句子一个匹配 .

    这有点挑战性,我希望它在大多数情况下都能正常工作 . 确定:句子是什么并不是那么简单?好吧,我决定,简单地将分割序列视为可定义的标点符号(var sep_punct ),然后是一个或多个白色空格,如果前面有一个大写字母或数字 .

    var WordsToMatch = new Array('fox', 'dog');
    
    var TestStr = 
    'The quick brown fox jumps over the lazy dog but the lazy dog is '+
    'quick of the mark to catch the brown fox. In general the ' +
    'fox versus the dog is not a good match.';
    
    // --- JOHNNY 5's FIRST WORD IN SENTENCE HIGHLIGHTER ---
    
    // highlight first occurence of word in each sentence
    function higlight_first_w_in_sentence(str, words)
    {
      // split the string at what we consider a sentence:
      // new sentences usually start with upper letters, maybe digits
      // split-sequence: sep_punct, followed by one or more whitespaces,
      // looking ahead for an upper letter or digit
      var sep_punct = '[.;?!]';
    
      // set the split-pattern, starting with sep_punct
      var pattern = new RegExp(sep_punct + "\\s+(?=[A-Z0-9])", "g");
    
      // remember split-sequence
      var sep = str.match(pattern); 
    
      // split str into sentences
      var snt = str.split(pattern); 
    
      // check sentences split
      if((typeof snt != 'undefined') && (Object.prototype.toString.call(snt) === '[object Array]'))
      {
        // now we loop through the sentences...
        for(var i = 0; i < snt.length; i++)
        {
          // and match each word case insensitive using word-boundaries (zero-with)
          for(var j = 0; j < words.length; j++)
          {
            var pattern = new RegExp("\\b" + words[j] + "\\b", "i");
    
            // and replace it with highlighted reference 0,
            // which is $& in JS regex (part, that matches the whole pattern)
            snt[i] = snt[i].replace(pattern, "<b>$&</b>");
          }
        }
    
        // if seperators, rejoin string
        if((typeof sep != 'undefined') && (Object.prototype.toString.call(sep) === '[object Array]') && (sep.length > 0) && 
           (typeof snt != 'undefined') && (Object.prototype.toString.call(snt) === '[object Array]') && (snt.length > sep.length)
          )
        {
          var ret = "";
          for(var j = 0; j < snt.length; j++)
          {
            if(j>0) {
              ret += (typeof sep[j-1] != 'undefined') ? sep[j-1] : " ";
            }
    
            ret += snt[j];
          }
    
          return ret;
        }
    
        // if no seperators
        return snt.join(" ");
      }
    
      // if failed
      return str;
    }
    
    document.write(higlight_first_w_in_sentence(TestStr, WordsToMatch));
    

    输出:

    快速的棕色狐狸跳过懒狗,但懒狗很快就 grab 了棕色的狐狸 . 一般来说,狐狸与狗不是很好的匹配 .

  • 4

    我有一段时间没有做过JavaScript,所以这段代码可能看起来很生气:

    matches = new Array('fox', 'dog');
    originalContent = 'The quick brown fox jumps over the lazy dog but the lazy dog is quick of the mark to catch the brown fox. In general the fox versus the dog is not a good match.';
    
    document.write(
                    highlight(originalContent, matches, 2)
                    + '<br>' +
                    preferredHighlight(originalContent, matches, 2)
    );
    
    function highlight(input, matches, max){
        var matchesStatistics = new Array();
        for(i = 0, c = matches.length; i < c;i++){ // Performance !!!
            matchesStatistics[matches[i]] = 0;
        }
        var re = new RegExp('\\b(?:' + matches.join('|') + ')\\b', 'g'); // Words regex
        var highlightedContent = input.replace(re, function(group0){
            matchesStatistics[group0]++;
            if(matchesStatistics[group0] > max){
                return group0;
            }else{
                return '<b>' + group0 + '</b>';
            }
        });
        return highlightedContent;
    }
    
    function preferredHighlight(input, matches, max){
        var sentenceRe = new RegExp('[\\s\\S]*?(?:[.?!]|$)', 'g'); // Sentence regex
        var wordRe = new RegExp('\\b(?:' + matches.join('|') + ')\\b', 'g'); // Words regex
    
        var highlightedContent = input.replace(sentenceRe, function(sentence){
            var matchesStatistics = 0;
            modifiedSentence = sentence.replace(wordRe, function(group0){
                matchesStatistics++;
                if(matchesStatistics > max){
                    return group0;
                }else{
                    return '<b>' + group0 + '</b>';
                }
            });
            return modifiedSentence;
        });
        return highlightedContent;
    }
    

    Output:

    快速的棕色狐狸跳过懒狗,但懒狗很快就 grab 了棕色的狐狸 . 一般来说,狐狸与狗不是很好的匹配 . 快速的棕色狐狸跳过懒狗,但懒狗很快就 grab 了棕色的狐狸 . 一般来说,狐狸与狗不是很好的匹配 .

    解释

    正则表达式

    • Words regex: 我们使用 .join('|') 来连接数组元素,因此对于此示例 . 我们的正则表达式看起来像 \\b(?:fox|dog)\\b . 我们使用 \b 确保仅匹配 fox 而不是 firefox . 需要双重逃逸 . 当然,将 g 修饰符设置为"replace all" .

    • Sentence regex: 好吧,让我们分开吧:

    • [\\s\\S]*? :匹配任何不合理的零次或多次 .

    • (?:[.?!]|$) :匹配 .?! 或行尾 .

    • g 修饰符:匹配全部 .

    突出显示功能:

    我们的想法是创建一个数组来记住我们对某些单词的匹配程度 . 因此,在我们的案例中运行以下代码时:

    var matchesStatistics = new Array();
    for(i = 0, c = matches.length; i < c;i++){ // Performance !!!
        matchesStatistics[matches[i]] = 0;
    }
    

    我们有一个看起来像这样的数组:

    Array(
        "fox" => 0,
        "dog" => 0
    )
    

    然后我们匹配我们的单词,并使用函数作为回调来检查我们匹配了多少以及是否应该突出显示 .

    首选突出显示功能:

    我们基本上,首先匹配每个句子然后我们替换单词(在每个句子中) . 这里的话也有一个限制 .

    在线演示

    References:

相关问题