【问题标题】:How to search array of strings and produce suggestive results如何搜索字符串数组并产生提示性结果
【发布时间】:2017-04-07 22:36:02
【问题描述】:

我在 JavaScript 中有一个字符串数组。我正在尝试开发一个功能,

  1. 将子字符串作为输入。
  2. 搜索数组。
  3. 从靠近子字符串的数组中返回字符串。该列表将作为建议提供给来电者。

例如:-

数组包含以下条目。

Hello
What is hello
World
Spacearenotthereinthishello
HELLO
Highway to hell
JavaScript
StackOverflow

我调用如下所示的函数

var 结果[] = searchFunc('hell');

结果数组应该包含

Hello
What is hello
Spacearenotthereinthishello
HELLO
Highway to hell

数组可能包含至少 100 个字符串(或更多)。我正在寻找可扩展的解决方案。

最初,我认为我应该排序,然后进行二进制搜索,但如果您想从主数组中提取特定字符串输入的所有建议,这样做很麻烦。我正在寻找可以帮助我实现更快搜索的算法。我并不担心主阵列中的插入时间复杂性。

我确实查找了多个堆栈溢出帖子。他们确实谈到在一本大书中搜索特定的字符串。他们都没有谈论从数组返回子字符串的建议。

感谢您的帮助。

【问题讨论】:

  • 如果您正在查看大约 100 个字符串,并且每个字符串可能有几十个字符长,那么使用 indexOf 的简单过滤器应该可以很好地扩展。如果您最终要获得 100,000 个元素,那么您可能需要开始研究用于 ngram 搜索的高级数据结构和算法。
  • 是的。这个问题的目的是看看其他人是否知道我可以实现的算法来创建一个可扩展的解决方案。 (如果它足够好,甚至开源它)。你知道有什么可以帮助我处理巨大的字符串数组吗?
  • 您可以使用a tool like this 来获取每个短语中的字符组合,并从每个不同的字符组合到它所在的短语构建一个对象/映射。或者您可以使用something like this这只是让您通常进行全文搜索。
  • @StriplingWarrior 我将检查 Lunr。我欠你一杯啤酒,甚至建议它。谢谢!

标签: javascript arrays string search


【解决方案1】:

YourArray.filter() 将完成这项工作。快速原型:

var results = arrayName.filter(function(value) {
  return value.toLowerCase().indexOf(searchStr.toLowerCase()) >= 0;
});

【讨论】:

  • 可能想要在过滤器之外评估searchStr.toLowerCase() 以避免不必要的额外工作。
  • 第二个参数可以与过滤器一起使用来传递小写:.filter(fn, searchStr.toLowerCase()),然后在它里面是.indexOf(this)。添加 `"use strict" 以避免额外的类型转换,但它仍然按原样工作......
  • 谢谢。我会稍微测试一下。我完全赞成使用本机功能,但对可扩展性有点怀疑。如果数组中有超过 500 个条目怎么办?
  • @NishM 使用 500 即可,但您可以轻松测试它。做一个循环,将 100 甚至 1000 个字符串推送到数组中,它可以是相同的字符串,不会有任何区别。此类查询的真正可扩展解决方案最好在数据库服务器上实现,例如使用全文索引。
【解决方案2】:

快速解答 (TL;DR)

  • 使用 Array.prototype.filter()

详细解答

上下文

  • Javascript
  • 数组过滤

问题

  • 场景: 开发人员希望过滤数组以匹配子字符串

解决方案

// 声明字符串片段数组 myArrayOfStringFragments = /* TODO: 获取内容 [ ... ] */ // 可选步骤,将所有字符串标准化为小写 /* TODO: 使用 Array.prototype.map() 或类似的东西进行输入规范化 */ // 声明比较函数 函数 strContainsMatch(slookfor) { 返回 slookfor.includes("ello"); } // 使用 Array.prototype.filter() 进行迭代 变种过滤 = myArrayOfStringFragments.filter(strContainsMatch);

陷阱

  • 数据输入标准化(基于字母大小写的差异是否显着?)
  • 基于非ASCII字符的字符串比较
  • string.includes() 方法可能不可用,改为使用 string.indexOf()
  • 避免基于所选子字符串的误报匹配
    • (例如,如果您正在寻找 hello,那么 hell 将匹配到比您想要的更多,如果您的输入未标准化为小写,它将错过 Hello

另见

【讨论】:

    【解决方案3】:

    另一种解决方案是创建一个正则表达式来做同样的事情。

    var condition = new RegExp("hell", 'g');
    
    var results = arrayName.filter(function(value) {
        return condition.test(value.toLowerCase())
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      • 2014-02-21
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多