【问题标题】:How to match two non-consecutive words in a String for React/Javascript search?如何在字符串中匹配两个不连续的单词以进行 React/Javascript 搜索?
【发布时间】:2021-03-15 02:22:29
【问题描述】:

我有一个依赖于这种过滤方法的搜索栏。 我将所有搜索字符串连接到变量concat 中,然后使用.includes().match(),如下所示。如果搜索多个单词,仅当单词在concat 中连续出现时才会返回结果。

但是,我希望它匹配 concat 中的任何两个单词,而不仅仅是连续的单词。有没有办法轻松做到这一点?

    .filter((frontMatter) => {
      var concat =
        frontMatter.summary +
        frontMatter.title +
        frontMatter.abc+
        frontMatter.def+
        frontMatter.ghi+
        frontMatter.jkl;
      return concat.toLowerCase().match(searchValue.toLowerCase());
    });

也试过了;

    .filter((frontMatter) => {
      const concat =
        frontMatter.summary +
        frontMatter.title +
        frontMatter.abc+
        frontMatter.def+
        frontMatter.ghi+
        frontMatter.jkl;
      return concat.toLowerCase().includes(searchValue.toLowerCase());
    });

谢谢!

【问题讨论】:

  • 所以你想要创建一个变量,将其设置为 true,为searchValue.toLowerCase().split(" ") 执行 forEach,每次检查它是否包含它,如果不包含,则将变量设置为 false ,然后在 forEach 之后只返回变量?
  • 你不想用空格或其他东西连接所有这些前物质部分吗?目前它只是将它们混合在一起,例如 title = "Hello there"abc = "abc"def = "def"...concat"Hello thereabcdef"

标签: javascript arrays reactjs search next.js


【解决方案1】:

一切都在代码的 cmets 中进行了解释。

如果您不在乎“阻止”与“未确定”一词匹配

.filter((frontMatter) => {
  // Get the front matter into a string, separated by spaces
  const concat = Object.values(frontMatter).join(" ").toLowerCase();

  // Look for a string in quotes, if not then just find a word
  const regex = /\"([\w\s\\\-]+)\"|([\w\\\-]+)/g;

  // Get all the queries
  const queries = [...searchValue.toLowerCase().matchAll(regex)].map((arr) => arr[1] || arr[2]);

  // Make sure that every query is satisfied
  return queries.every((q) => concat.includes(q));
});

如果您确实关心“阻止”不应匹配“未确定”一词

.filter((frontMatter) => {
  // Get the front matter into a string, separated by spaces
  // The prepended and appended spaces are important for the regex later!
  const concat = ` ${Object.values(frontMatter).join(" ").toLowerCase()} `;

  // Look for a string in quotes, if not then just find a word
  const regex = /\"([\w\s\\\-]+)\"|([\w\\\-]+)/g;

  // Get all the queries
  const queries = [...searchValue.toLowerCase().matchAll(regex)].map((arr) => arr[1] || arr[2]);

  // Make sure that every query is satisfied
  // [\\s\\.?!_] and [\\s\\.?!_] check for a space or punctuation at the beginning and end of a word
  // so that something like "deter" isn't matching inside of "undetermined"
  return queries.every((q) => new RegExp(`[\\s\\.?!_]${q}[\\s\\.?!_]`).test(concat));
});

【讨论】:

  • 哦,没问题。抱歉,添麻烦了。这行得通。惊人的答案。每个值末尾的“”怎么样,就像您在问题评论中提到的那样。有必要吗?
  • 已更新。它是必需的,因为例如,您正在搜索 "carpet". If one value ended in "car", and the next one started with "pet", you would find "carpet"`,因为地毯本身从来就不是一个词。 (顺便说一句,如果这对您有用,请单击 upvote/downvote 部分的灰色/绿色复选标记,将其标记为正确的解决方案)
  • 我使用了您更新的解决方案。可能有问题。对于我在早期代码中使用的特定搜索字符串,我得到了 56 个结果(这是正确的数字),但是对于相同的搜索字符串,我现在只得到 32 个结果。即使按照解决方案中的逻辑,我应该看到数字增加,因为它现在匹配更多的单词,而不是减少。我很困惑。
  • 如果搜索中的所有单词都出现在前面,则返回 true,如果有任何单词不匹配,则返回 false。你想要一些不同的东西吗?
  • 是的,我希望 searchValue 中的任何单词与 frontMatter.xyz 中的任何单词匹配。例如,搜索 ABC DEF 应该返回所有包含 ABC 和 DEF 或 ABC 和 DEF 的 frontMatter 帖子。另外,我通过像“frontMatter.length”这样的操作来计算匹配的数量。
【解决方案2】:

我会使用.reduce 来计算匹配的数量,如果至少有 2 个则返回 true:

const props = ['summary', 'title', 'abc', 'def', 'ghi', 'jkl'];
// ...
.filter((frontMatter) => {
  const lowerSearch = searchValue.toLowerCase();
  const matchCount = props.reduce(
    (a, prop) => a + lowerSearch.includes(frontMatter[prop].toLowerCase()),
    0
  );
  return matchCount >= 2;
})

【讨论】:

  • 不要将concat 定义为带有const concat = frontMatter.summary + frontMatter.title + 等的字符串,而是定义一个属性数组,然后对其进行迭代。在我的回答中,您根本不会使用 concat 字符串。
  • 您没有像我在答案中那样定义道具。完全使用const props = ['summary', 'title', 'abc', 'def', 'ghi', 'jkl'];。如果您执行const props = [ frontMatter.summary, frontMatter.title, 等,您将在frontMatter 对象中拥有一个 数组,而不是frontMatter 对象上存在的属性 数组.
  • 如果你想遍历对象中的所有属性,你也可以使用Object.values而不是硬编码属性。
  • @CertainPerformance 检查每个属性的值是否在lowerSearch 内。这应该是另一种方式,您检查lowerSearch 中的每个单词并查看它是否在任何属性中,并且lowerSearch 中的多个单词可能在每个属性中,所以这看起来完全是错误的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多