【问题标题】:An efficient Javascript set structure一个高效的 Javascript 集合结构
【发布时间】:2013-06-12 20:26:28
【问题描述】:

看了很多类似的问题后:

我还有一个问题:假设我有一个大字符串数组(几千个),我必须进行多次查找(即多次检查给定字符串是否包含在这个数组中)。在 Node.js 中执行此操作的最有效方法是什么?

A.对字符串数组进行排序,然后使用二进制搜索?或:

B.将字符串转换为对象的键,然后使用“in”运算符

?

我知道A的复杂度是O(log N),其中N是字符串的个数。

但我不知道 B 的复杂性。

如果一个 Javascript 对象被实现为哈希表,那么 B 的复杂度平均为 O(1),比 A 好。但是,我不知道 Javascript 对象是否真的实现为一个哈希表!

【问题讨论】:

  • 在 V8 中对象属性查找几乎是即时的,并且没有二分查找。您可以使用 [].filter(/./.test, /^bob$/i) 来查找“bob”的字符串元素,这比用户域搜索代码要快...
  • @apsillers 我编辑了我的问题,以表明我主要对 Node.JS 实现感兴趣。
  • @dandavis 我几乎可以肯定,一个简单的Array.indexOf() 会更快。
  • 如果任何 JS 实现不使用散列或其他相当有效的方法来实现对象,那将是非常令人惊讶的。
  • @ErelSegalHalevi 只是在这个fiddle(最好在 Chrome 中)玩一点,或者直接在 node.js 中做类似的事情。我只测试了indexOf 与对象属性查找,是的,对象属性查找速度非常快,而且似乎执行时间为 O(1)。

标签: performance node.js


【解决方案1】:

2016 年更新

由于您询问的是 node.js 并且是 2016 年,因此您现在可以使用 ES6 中的 SetMap 对象,因为它们已内置于 ES6 中。两者都允许您使用任何字符串作为键。当您只想查看密钥是否存在时,Set 对象是合适的:

if (mySet.has(someString)) {
    //code here
}

而且,Map 适用于您想要存储该键的值,如下所示:

if (myMap.has(someString)) {
    let val = myMap[someString];
    // do something with val here
}

从 node V4 开始,这两个 ES6 功能现在都内置在 node.js 中(本次编辑时 node.js 的当前版本是 v6)。

查看this performance comparison,了解Set 操作比许多其他选择快多少。

旧答案

所有重要的性能问题都应在 jsperf.com 等工具中通过实际性能测试进行测试。在您的情况下,javascript 对象使用类似哈希表的实现,因为如果没有性能很好的东西,整个实现会很慢,因为很多 javascript 都使用对象。

对象上的字符串键将是我要测试的第一件事,也是我对性能最佳者的猜测。由于对象的内部是在本机代码中实现的,我希望这比您自己在 javascript 中实现的哈希表或二进制搜索更快。

但是,当我开始回答时,您应该在 jsperf 等工具中使用您最关心的字符串的数量和长度来测试您的具体情况。

【讨论】:

  • 谢谢,但我主要对 Node.JS 实现感兴趣(我编辑了我的问题以反映这一点),所以 jsperf.com 不相关。
  • @ErelSegalHalevi - 然后在 node.js 中设计您自己的性能测试,或者在 node.js 中使用来自 jsperf.com 的基准测试引擎。 node.js 与 Chrome 中的 javascript 引擎相同,因此您可以通过在 Chrome 浏览器中尝试 jsperf.com 来获得一阶结果。如果您想在 node.js 中验证这一点,则必须将自己的基准测试移至 node.js。这里的答案不会在银盘上交给你。如果您真的想知道哪个更快,您必须测试您的特定情况。我建议您使用已经构建的性能基准测试工具。
【解决方案2】:

对于固定的大型字符串数组,我建议使用某种形式的radix search 另外,请查看this package中的不同数据结构和算法(AVL 树、队列/堆等)

我很确定使用 JS 对象作为字符串的存储将导致该对象的“哈希模式”。根据实现,这可能是 O(log n) 到 O(1) 时间。查看 some jsperf benchmarks 比较属性查找与排序数组上的二进制搜索。

在实践中,特别是如果我不打算在浏览器中使用代码,我会将这个功能卸载到 redis 或 memcached 之类的东西上。

【讨论】:

猜你喜欢
  • 2011-02-01
  • 2013-01-26
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
  • 2018-07-25
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
相关资源
最近更新 更多