Javascript 快速查找字符串是否在数组中的方法

Javascript 快速查找字符串是否在数组中的方法,javascript,arrays,set,Javascript,Arrays,Set,在Ruby中,查找字符串是否在数组中(.include?x)非常慢。如果您将该数组更改为一个集合,则BAM,将进行闪电般快速的查找 在JavaScript中,如果没有集合,数组查找(.indexOf(x)>=0)也会非常慢,但是我需要在脚本中执行10000次这些查找 我的Ruby版本(带集合)运行时间为0.125秒,我的JavaScript版本(NodeJS)运行时间为29 是否有一个集合库或更好的方法来执行数组查找,从而使Javascript的速度接近Ruby 编辑:将“对象”更改为“字符串”

在Ruby中,查找字符串是否在数组中(
.include?x
)非常慢。如果您将该数组更改为一个集合,则BAM,将进行闪电般快速的查找

在JavaScript中,如果没有集合,数组查找(
.indexOf(x)>=0
)也会非常慢,但是我需要在脚本中执行10000次这些查找

我的Ruby版本(带集合)运行时间为
0.125
秒,我的JavaScript版本(NodeJS)运行时间为
29

是否有一个集合库或更好的方法来执行数组查找,从而使Javascript的速度接近Ruby


编辑:将“对象”更改为“字符串”,以消除注释中@nnnn的任何混淆

将数组转换为对象,如下所示:

object = {}
array.forEach(function(string) { // Not cross-browser compatible, it's just an example
  object[string] = 1;
}
if (string in object) {
然后执行如下查找:

object = {}
array.forEach(function(string) { // Not cross-browser compatible, it's just an example
  object[string] = 1;
}
if (string in object) {

首先,这里有一些关于JavaScript中可用的数据结构的基本混淆

JavaScript没有数组

基本上,JavaScript只有哈希表。标准的
Array
函数构造散列表(我将称这些整数散列表或int散列表),其中的键是除字符串键之外的整数。它们的性能类似于数组,但在某些方面有所不同。有利也有弊。例如,从int哈希表中删除元素是一个O(1)操作,而从数组中删除元素是一个O(n)操作(因为需要将其余元素复制到新数组中)。这就是JavaScript中
Array.prototype.splice
函数速度非常快的原因。缺点是实现的复杂性

因此,当您在JavaScript上下文中说
Array
时,它被理解为int哈希表,以及与之相关的所有渐进复杂性。这意味着,如果您想在int哈希表中查找字符串值,那么它将是一个O(n)操作。有一个标准函数可以执行此操作:
Array.prototype.indexOf
。但是,如果要查找键,则有两个函数:中的
Object.prototype.hasOwnProperty

有点违反直觉:

[1, 2, 3].hasOwnProperty(0); // true
0 in [1, 2, 3]; // true
两者之间的区别需要进一步解释。这与JavaScript中的所有东西都是对象这一事实有关,因此它们具有一些object-y特性。其中一个特性是
原型
,即对象与其原型之间的链接。它是哈希表的层次结构,每个哈希表包含对象的属性

  • 中查找对象的即时哈希表,然后递归搜索此对象原型的哈希表

  • Object.prototype.hasOwnProperty
    只查看立即哈希表。你可能认为应该更快,但等着下结论吧

由于JavaScript的动态特性,所有函数调用都是动态的,环境必须非常小心以确保代码执行的故障安全性。这意味着JavaScript中的函数调用非常昂贵。因此,使用
Object.prototype.hasOwnProperty
可能比在
中使用
要昂贵得多,尽管理论上应该相反。然而,给定足够高的继承树和足够多的继承属性,最终,
Object.prototype.hasOwnProperty
将接管

获得更好直觉的一些示例:

>>> var array = [1, 2, 3];
undefined
>>> 3 in array;
false
>>> array.hasOwnProperty(3);
false
>>> 3 in array;
false
>>> array.__proto__ = [1, 2, 3, 4];
[1, 2, 3, 4]
>>> 3 in array;
true
>>> array.hasOwnProperty(3);
false
TL;DR

  • 如果希望对具有短原型继承链的对象进行最快的键查找,请在
中使用

  • 如果您想要相同的,但对于具有广泛继承链的对象,请使用
    Object.prototype.hasOwnProperty

  • 如果想要最快的值查找,请使用
    Array.prototype.indexOf
    查找
    Array

  • 哈希表中没有用于值查找的内置函数。当然,您可以自己滚动,但是有许多库已经提供了一个。例如,下划线提供了一个(它称之为
    indexOf


  • 物体的结构是什么?如果它们具有某种唯一的id属性,您可以使用该id作为键将它们存储在对象中。@nnnnnn它只是一个字符串数组(
    [“foo”、“bar”、“baz”]
    )。对不起,我没说清楚。唯一的字符串?尝试一个对象
    var o={“foo”:1,“bar”:1,“baz”:1}
    ,然后尝试
    如果o中的(“foo”)存在{/*存在*/}
    。你有没有尝试对上面提到的foo
    中的
    “字符串”计时?@asifrc哇,它工作得完美无缺!脚本在
    0.250秒内完成!谢谢大家!请参阅中的基准,以查看真实世界的速度比较。