JavaScript 是否有一组数据结构的实现?

IT技术 javascript data-structures set
2021-02-26 19:25:14

我正在寻找 JavaScript 中集合数据结构的体面实现。它应该能够支持纯 JavaScript 对象的元素。

到目前为止,我只找到了Closure Library 的 structs.Set,但我不喜欢它修改我的数据的事实。

6个回答

ECMAScript 6 拥有它

规范:http : //www.ecma-international.org/ecma-262/6.0/#sec-set-constructor

用法:https : //github.com/lukehoban/es6features#map--set--weakmap--weakset

例子:

var s = new Set()
s.add("hello").add("goodbye").add("hello")
s.size === 2
s.has("hello") === true

一个为不支持的浏览器实现它的module:https : //github.com/medikoo/es6-set

这不适用于 JS 对象。对象被保留作为参考。具有相同属性值的对象将被视为两个对象并添加到 Set 中。
2021-04-16 19:25:14

您可以围绕我的jshashtable提供的哈希表的键构建一个简单的包装器我有一个在某处敲门,稍后我会挖出来。

更新

我已经完成并测试了 HashSet 的实现并将其上传到 GitHub 上的 jshashtable 项目。您可以下载它查看源代码

var s = new HashSet();
var o1 = {name: "One"}, o2 = {name: "Two"};
s.add(o1);
s.add(o2);
s.values(); // Array containing o1 and o2
它在文档中,但总而言之:哈希码是字符串,您可以向Hashtable构造函数提供一个计算哈希码的函数(以及一个比较两个对象并确定它们是否相等的函数)。否则,它会寻找hashCode()在键上调用的方法作为最后的手段,它尝试使用toString()将密钥转换为字符串String()如果您的所有键都散列到相同的值(例如“[object Object]”),因为您没有使用上述任何机制,那么它们都将进入同一个存储桶,并且必须使用您的简单线性搜索。
2021-04-15 19:25:14
你能解释一下你的库是如何计算对象哈希码的吗?
2021-04-26 19:25:14
嗨蒂姆,这个库会在集合中存储以下格式吗var o1 = {firstname: "John", lastname: "Doe"}, o2 = {firstname: "Eric", lastname: "Lencher"}
2021-05-03 19:25:14

我认为除了将其存储在对象本身中之外,没有其他方法可以处理对象的哈希码。严格来说,可以使用简单的线性搜索创建一个没有散列的集合类,但这几乎没有效率。

的确。除了将它与其他所有对象进行比较之外,没有办法在 JS 中获取对象的身份。
2021-05-14 19:25:14

使用ECMAScript 2015 (ES6) 标准的 Set Data 结构非常好用:

var mySet = new Set();

mySet.add(1);
mySet.add(5);
mySet.add("some text");
var o = {a: 1, b: 2};
mySet.add(o);

mySet.has(1); // true
mySet.has(3); // false, 3 has not been added to the set
mySet.has(5);              // true
mySet.has(Math.sqrt(25));  // true
mySet.has("Some Text".toLowerCase()); // true
mySet.has(o); // true

mySet.size; // 4

mySet.delete(5); // removes 5 from the set
mySet.has(5);    // false, 5 has been removed

mySet.size; // 3, we just removed one value

为那些使用 AngularJs 的人更新

请注意,集合不适用于ng-repeat. 所以最好使用数组并应用唯一的过滤器

在 ES6 版本的 Javascript 中,您已经为set内置了类型检查与浏览器的兼容性)。

var numbers = new Set([1, 2, 4]); // Set {1, 2, 4}

要将元素添加到集合中,您只需使用.add(),它运行O(1)并添加元素以设置(如果它不存在)或者如果它已经存在则不执行任何操作。您可以在那里添加任何类型的元素(数组、字符串、数字)

numbers.add(4); // Set {1, 2, 4}
numbers.add(6); // Set {1, 2, 4, 6}

检查集合中的元素数量,您可以简单地使用.size. 也跑进去O(1)

numbers.size; // 4

要从集合中删除元素,请使用.delete(). 如果该值存在(并被删除),则返回 true,如果该值不存在,则返回 false。也运行在O(1).

numbers.delete(2); // true
numbers.delete(2); // false

检查元素是否存在一组使用.has(),如果元素是集合,否则为false返回true。也运行在O(1).

numbers.has(3); // false
numbers.has(1); // true

除了您想要的方法之外,还有一些其他方法:

  • numbers.clear(); 只会从集合中删除所有元素
  • numbers.forEach(callback); 按插入顺序迭代集合的值
  • numbers.entries(); 创建所有值的迭代器
  • numbers.keys(); 返回与集合相同的键 numbers.values()

还有一个 Weakset 只允许添加对象类型的值。

您确定 Set 中的插入在 O(1) 中运行吗?我无法找到任何这样的实现,并且我发现它的运行时间为 O(N) 并且该实现具有 indexOf 方法,该方法检查该值是否存在于数组中。我需要在循环内使用它,因此我对使用 indexOf 方法犹豫不决。你能指出我的任何实现或你阅读的资源吗?
2021-04-15 19:25:14
@Vatsal 是的,将元素插入到集合需要 O(1) 分摊时间。我不知道在哪里可以找到 JS 中集合的实现,但是数据结构中的每本基础书籍都会证实这一点。IndexOf 是一种对数组进行操作的方法,因此它需要 O(n) 时间也就不足为奇了。
2021-04-23 19:25:14