首页 > 解决方案 > 突出显示目标词串中的搜索词匹配

问题描述

任务:给定一个由一个或多个单词组成的搜索词,突出显示在一个或多个单词的目标字符串中找到的每个单词。请注意,搜索词可以以任何顺序出现,并且即使不是所有词都在目标字符串中找到,也应该匹配。

原因:通过突出显示匹配项来帮助用户了解目标字符串与搜索词匹配的原因。

要求:我也希望它不区分大小写。

它应该处理简单的情况

针: Foo bar
干草: I pity the fool
期望的结果:我可怜那个傻瓜

它应该匹配多个按字符串分割的搜索词,以目标字符串中的任意顺序

针: Foo bar
干草: I pity the bar fool
期望的结果:我同情酒吧 傻瓜

它应该处理搜索词可能相互冲突的情况

针: Barbeque bar
干草: Quality barbeque grill
期望结果:优质烧烤

标签: javascripthtmlregexsearchfull-text-search

解决方案


我的解决方案基于:

  1. 将搜索词拆分为搜索词。
  2. 逐一遍历目标字符串,查看搜索词是否存在于目标字符串中。这是通过拆分搜索词来完成的。
    • 具有奇数索引的那些将是要突出显示的单词(如果未找到匹配项,则结果的长度为1,该项目的索引为0)。
  3. 将结果反馈到第 2 步,但仅尝试在目标字符串中突出显示尚未突出显示的部分。

就我个人而言,我直接将输出数组与 Vue 一起使用,并让它处理模板任务,但在这里包含了一个示例,说明它如何输出要呈现的简单 HTML。

<script lang="js">
  const splitHighlight = (arrayOfStrings, highlightWord) => {
    // use () for capture and keeping the matched string, and `i` for case
    // insensitive matching
    const regex = new RegExp(`(${highlightWord})`, "i");
    return arrayOfStrings
      .map((s, i) => {
        // if the index is odd then then this string is already highlighted,
        // so don't try to highlight within the highlight
        const isAlreadyHighlighted = i % 2 !== 0;
        return isAlreadyHighlighted ? [s] : s.split(regex);
      })
      .flat();
  };

  const splitNeedlesInHay = (needlesStr, hay) => {
    const needlesArray = needlesStr.trim().split(" ");
    let hayArray = [hay];
    needlesArray.forEach((n) => (hayArray = splitHighlight(hayArray, n)));
    return hayArray;
  };

  const highlightNeedlesInHay = (needlesStr, hay) => {
    const needlesInHay = splitNeedlesInHay(needlesStr, hay);
    console.log(needlesInHay);

    const transformHayArrayToHtmlReducer = (acc, curr, index) => {
      return acc + (index % 2 === 0 ? curr : `<b>${curr}</b>`);
    };

    return needlesInHay.reduce(transformHayArrayToHtmlReducer);
  };
  
  const result1 = highlightNeedlesInHay("Foo bar", "I pit the fool");
  console.log(result1);
  document.write(result1 + "<br />");
  
  const result2 = highlightNeedlesInHay("Foo bar", "I pit the bar fool");
  console.log(result2);
  document.write(result2 + "<br />");
  
  const result3 = highlightNeedlesInHay("Barbeque bar", "Quality barbeque grill");
  console.log(result3);
  document.write(result3 + "<br />");
</script>


推荐阅读