简体   繁体   English

高亮显示字符串中的文本

[英]Highlight text within a string

I have an algorithm which calculates the characters to highlight in text based on query. 我有一种算法,可以根据查询来计算要突出显示在文本中的字符。

For example, if I pass to the algorithm text "1000, Brussels, Belgium" and query "1000 bruss" it will return me [[0, 4], [6, 11]] . 例如,如果我传递给算法文本“ 1000,Brussels,Belgium”并查询“ 1000 bruss”,它将返回我[[0, 4], [6, 11]] 6,11 [[0, 4], [6, 11]] But now, I need to write an algorithm which will wrap the characters with <strong></strong> , so the result should be <strong>1000</strong>, <strong>Bruss</strong>els, Belgium . 但是现在,我需要编写一种算法,该算法将使用<strong></strong>包装字符,因此结果应该是<strong>1000</strong>, <strong>Bruss</strong>els, Belgium I wrote the algorithm, but i have a feeling it might be better or it might be solved more elegant. 我写了算法,但是我觉得它可能会更好,或者可能会更优雅地解决。

const highlight = (content, query, matches) => {
  if (!query) {
    return content;
  }

  const openTag = "<strong>";
  const closeTag = "</strong>";

  let result = content;
  let shift = 0;

  matches.forEach(([startIndex, endIndex]) => {
    const s =
      openTag +
      result.slice(startIndex + shift, endIndex + shift) +
      closeTag +
      result.slice(endIndex + shift);

    if (shift) {
      result = result.slice(0, startIndex + shift) + s;
    } else {
      result = s;
    }

    shift += openTag.length + closeTag.length;
  });

  return result;
};

Is there any better way to solve the problem? 有没有更好的方法来解决问题?

Another example: 另一个例子:

  • Text: 'Amsterdam, North-Holland, Netherlands' 文字:“荷兰北荷兰省阿姆斯特丹”
  • Query: 'amst' 查询:“ amst”
  • Matches: [0, 4] 匹配: [0, 4]

You could sort the matches in ascending order, then you can just take the parts between the marches and concatenate them alltogether: 您可以按升序对比赛进行排序,然后可以将行进之间的部分合并在一起:

 const highlight = (content, matches) => {
   matches.sort(([a], [b]) => a - b);

  let result = "";
  let prevEnd = 0;
  for(const [start, end] of matches) {
    result += content.slice(prevEnd, start);
    result += "<strong>";
    result += content.slice(start, end);
    result += "</strong>";
    prevEnd = end;
  }
  result += content.slice(prevEnd);
  return result;
}

(This assumes that matches do not overlap, just like the OPs code) (这假定匹配项不重叠,就像OPs代码一样)


Alternatively you can leave the replacement up to the regex engine: 或者,您可以将替换项留给正则表达式引擎:

 const result = content.replace(new RegExp(query.split(" ").join("|"), "g"), it => `<strong>${it}</strong>`);

Consider using mark.js 考虑使用mark.js

Replacing nodes in the DOM can be tricky and lead to unintended consequences as elements shift and fire events. 替换DOM中的节点可能很棘手,并且在元素移动和触发事件时会导致意想不到的后果。 Although it adds a third party dependency, it has a pretty clean API and abstracts away the logic so you don't have to own it. 尽管它添加了第三方依赖性,但它具有非常干净的API,并且抽象了逻辑,因此您不必拥有它。

 var instance = new Mark(".mark-context"); instance.mark("100 bruss"); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js"></script> <p class="mark-context"> 1000, Brussels, Belgium </p> 

Another alternative can be to split the string into characters : 另一种选择是将字符串拆分为字符:

 var text = '1000, Brussels, Belgium', query = [[0, 4], [6, 11]], chars = [...text]; query.forEach(([from, to]) => { chars[from] = '<strong>' + chars[from]; chars[to] = '</strong>' + chars[to] }); document.body.innerHTML = chars.join('') console.log( chars ) 

You can use the power of Regular Expressions (RegEx) to do this! 您可以使用正则表达式(RegEx)的功能来执行此操作! See the following function below, simply set string to the text you are searching through, and search to the text you want to find. 请参阅下面的以下功能,只需将string设置为要搜索的文本,然后search要查找的文本。 In your case, string would be "1000, Brussels, Belgium" and search would be "1000 bruss" 在您的情况下, string为“ 1000,比利时布鲁塞尔”,而search结果为“ 1000 bruss”

function highlightString(string, search){
var regEx = new RegExp(search, 'g');
return str.replace(regEx, '<strong>'+search+'</strong>');

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM