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

时间:2014-01-01 21:18:09

标签: javascript regex

如何突出显示x次出现

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

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

原创内容

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

突出显示的内容

快速的棕色狐狸跳过懒惰的但懒惰的很快就能抓住棕色的狐狸即可。一般来说,狐狸与狗不是很好的匹配。


对于额外的积分,我最好只在每个句子中突出显示一个匹配。

首选突出显示的内容

快速的棕色狐狸跳过懒惰的,但懒狗很快就抓住了棕色的狐狸。一般来说,狐狸并不是一个很好的匹配。

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

2 个答案:

答案 0 :(得分:4)

我的解决方案在模式中使用replace() word-boundariesglobal modifier g

替换的优点是,回调函数可以作为替换传递。我希望你喜欢它,发现它非常有趣,因为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;
}

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

输出:

  

快速的棕色狐狸跳过懒惰的但懒惰的很快就能抓住棕色的狐狸即可。一般来说,狐狸与狗不是很好的匹配。


编辑:现在我看到,还有额外的积分......

  

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

这更具挑战性,我希望它在大多数情况下都能正常工作。确定一句并不是那么简单:什么是句子?我决定,简单地将分割序列视为可定义的标点符号( 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));

输出:

  

快速的棕色狐狸跳过懒惰的,但懒狗很快就抓住了棕色的狐狸。一般来说,狐狸并不是一个很好的匹配。

答案 1 :(得分:2)

我暂时没有完成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;
}

<强>输出:

  

快速的棕色狐狸跳过懒惰的但懒惰的很快就能抓住棕色的狐狸即可。一般来说,狐狸与狗不是很好的匹配。

     

快速的棕色狐狸跳过懒惰的,但懒狗很快就抓住了棕色的狐狸。一般来说,狐狸并不是一个很好的匹配。

说明

正则表达式

  • 单词regex:我们使用.join('|')加入数组元素,因此对于此示例。我们的正则表达式看起来像\\b(?:fox|dog)\\b。我们使用\b确保仅匹配fox而不是firefox。需要双重逃逸。当然,将g修饰符设置为“全部替换”。
  • 句子正则表达式:好吧,让我们分开吧:
    • [\\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
)

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

首选突出显示功能:

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

Online demo

<强>参考文献: