【问题标题】:What is the most optimal way to check if something in an array exists?检查数组中是否存在某些内容的最佳方法是什么?
【发布时间】:2020-01-31 20:40:27
【问题描述】:

我正在创建的项目涉及对数组进行多次搜索,我意识到如果我不这样做,我可能会看到服务器性能问题的最佳方式。

我想知道在数组中查找值的服务器密集程度最低的方法是什么,不胜感激。

我看到有人在这个网站上回答这个问题,但答案不一,有人说基本的 for 循环是最好的,其他人说 indexOf 和 findIndex 会表现更好,但不确定哪个最好,或者是否有不同的选择。

【问题讨论】:

  • 为什么使用数组而不是集合?
  • 原生 JS js 总是最好的:yourArray.indexOf("value") > -1
  • 比较 arrayset 的搜索复杂度是 O(N) 与 O(1)。
  • @Camille 你应该告诉MDN 然后;)还有节点,即服务器端JS。

标签: javascript


【解决方案1】:

在长度为n 的数组中搜索的时间复杂度为O(n),而使用Map 的时间复杂度为O(1),因为您无需遍历Map 即可知道是否特定元素存在于其中。您可以使用其key 获取该元素。

如果元素存在,会在O(1)时间返回,否则你会得到undefined,意思是你搜索的元素在Map中不存在

因此,在您的情况下,最好使用 Map 而不是数组。

【讨论】:

  • 我会说使用 Set - 如果您没有键值关系并且数组大多没有,那么 Map 没有真正的好处。除非索引很重要,但只是搜索有点怀疑)。
  • @VLAZ 但是,如果它们是我放入集合中的对象,那么它不会起作用,对吧?当我测试它时,如果我在集合中请求相同的对象,似乎集合中的 .has 方法会返回 false,但我不确定
  • @Buckets 取决于您要搜索的内容。如果它是一个对象,那么您需要原始引用,但Array#indexOfArray#includes 也是如此。既然您提到了这些,我假设您正在搜索原语或现有对象。如果您需要按参数进行搜索,这不会反映在您的问题中。
  • @Buckets 这就是为什么我建议使用Map 而不是Set。在Map 中,您可以在Map 中添加对象时提供唯一的key。当您需要搜索任何对象时,只需使用其key
【解决方案2】:

即使是通过列表进行最优化的搜索,其运行时复杂度也会达到O(n)。基本的 for 循环将是最快的,因为您可以让它在第一次出现时终止。当您搜索对象时,事情会变得更有趣。

function arrayHasObj(obj, list) {
  var i = list.length;
  while (i--) {
    if (JSON.stringify(list[i]) === JSON.stringify(obj)) {
      return true;
    }

    return false;
  };
}

这里的while 循环显然是O(n),但我们还需要考虑将对象序列化为JSON。这不属于任何标准的时间复杂度分析。如果有人可以权衡这一点,请这样做。


通常不需要通过单个数组优化搜索。您的算法需要进行一些更大的优化,或者如果您真正使用的是大型数据集,则应该使用从数据库中查询。

编辑: 显然,字典/集有其优点。 OP专门询问数组。

【讨论】:

  • "即使是最优化的列表搜索也会有 O(n) 的运行时复杂度"???在O(log(n)) 中可以轻松地对排序列表进行二分搜索。如果您维护一个带有哈希结构的查找表,那么您的搜索将是 O(1) 并具有良好的哈希算法和分桶。
  • 我们不能假设列表已经排序,它从未被指定。使用标准快速排序对列表进行排序会增加 O(n * log(n)) 的运行时间。
  • 现在您正在做一个假设 - 列表可能已经排序或静态。如果它没有改变,那么执行一次O(n*log(n)) 来加速许多查找是可以忽略不计的。我对 any 搜索是O(n) 的断言提出异议。当然,它增加了假设,但它也需要假设才能声明其他内容。
  • 这将取决于实现,但 因为它需要解析。此外,它是不可靠的 - JSON.stringify({a:1, b:2}) === JSON.stringify({b:2, a:1}) 可能会或可能不会工作,具体取决于平台,它不工作的可能性很大。 JSON.stringify({a:1, b:2}) === JSON.stringify({a:1, b: 2}) 有更高的成功机会,但它仍然依赖于平台。问题是 JS 不支持键的一致排序 until ES6 而那不是
  • 在每个平台上实施。即使它,您也可能陷入陷阱:JSON.stringify({a: 1, 1: true}) === JSON.stringify(1: true, a: 1) 在兼容的平台上,因为数字键会放在前面。然后,您还会遇到仅限于 JSON 可序列化内容的问题 - 函数和(非基本)对象将具有不同的表示形式,undefined 不存在于 JSON 中,并且不支持符号键。所以,这不是一个完美的解决方案。
猜你喜欢
  • 2012-06-17
  • 2011-05-25
  • 2012-08-29
  • 2011-10-11
  • 2010-09-18
相关资源
最近更新 更多