在Eloquent JavaScript第4章中,通过创建对象并将值存储为属性名称,将任意值(例如,true)指定为属性值来创建一组值。要检查该值是否已包含在集合中,请使用in
运算符:
var set = {};
if (!'Tom' in set) {
set.Tom = true;
}
这是惯用的JavaScript吗?不会更好地使用阵列吗?
var set = [];
if (!'Tom' in set) {
set.push = 'Tom';
}
答案 0 :(得分:82)
Sets现在可用于ES2015(又名ES6,即ECMAScript 6)。自2015年6月以来,ES6一直是JavaScript的当前标准。
ECMAScript 6具有适用于任意的数据结构Set 值,快速并正确处理NaN。 - Axel Rauschmayer,Exploring ES6
Axel Rauschmayer's本书Exploring ES6中的前两个例子:
管理单个元素:
> let set = new Set();
> set.add('red')
> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false
确定Set的大小并清除它:
> let set = new Set();
> set.add('red')
> set.add('green')
> set.size
2
> set.clear();
> set.size
0
如果您想了解有关JavaScript中的集合的更多信息,我会查看Exploring ES6。这本书可以免费在线阅读,但如果你想支持作者Dr. Axel Rauschmayer,你可以以30美元左右的价格购买这本书。
如果你现在想使用套装和ES6,你可以使用Babel,ES6到ES5的转换器及其polyfill。
编辑:截至2017年6月6日,大多数主流浏览器在其最新版本(IE 11除外)中都有完整的Set支持。这意味着如果您不关心支持旧版浏览器,则可能不需要使用babel。如果您想查看包括当前浏览器在内的不同浏览器的兼容性,请选中Kangax's ES6 compatibility table。
答案 1 :(得分:31)
我使用dict对象作为集合。这适用于字符串和数字,但是如果你想使用自定义相等和比较运算符来创建一组对象,我想会产生问题:
创建一个集合
var example_set =
{
'a':true,
'b':true,
'c':true
}
测试是否包含在
中if( example_set['a'] ){
alert('"a" is in set');
}
将元素添加到集合
example_set['d'] = true;
从集合中移除元素
delete example_set['a']
;
答案 2 :(得分:15)
集合不允许重复条目,通常不保证预定义的排序。数组执行这两个操作,因此违反了集合的含义(除非您进行其他检查)。
答案 3 :(得分:11)
第一种方式是惯用的JavaScript。
只要您想存储键/值对,就必须使用JavaScript对象。至于数组,有几个问题:
索引是一个数值。
没有简单的方法可以检查数据是否在数组中而没有循环。
一组不允许重复。数组呢。
答案 4 :(得分:7)
如果要从数组创建集合,只需执行:
let arr = [1, 1, 2, 1, 3];
let mySet = new Set(arr); // Set { 1, 2, 3 }
这是一种糖语法,我在Python编程时非常喜欢,很高兴ES6最终能够做同样的事情。
注意:然后我意识到我所说的并没有直接回答你的问题。你在ES5中遇到这种“黑客”的原因是因为按键在对象中的查找时间(O(1))比在数组中的查找时间(O(n))要快得多。在性能关键型应用程序中,您可以牺牲这一点可读性或直觉来获得更好的性能。
但是,嘿,欢迎来到2017年,您现在可以在所有主流现代浏览器中使用正确的设置!
答案 5 :(得分:4)
ES6
/ ES2015
中设置: ES6
/ ES2015
现在具有内置集合。集合是一种数据结构,它允许存储任何类型的唯一值,无论是原始值还是对象引用。可以使用内置ES6
的内置构造函数以以下方式声明一个集合:
const set = new Set([1, 2, 3, 4, 5]);
使用Set构造函数创建集合时,我们新创建的集合对象继承自Set.prototype
。这具有各种辅助方法和属性。这使您可以轻松地执行以下操作:
const set = new Set([1, 2, 3, 4, 5]);
// checkout the size of the set
console.log('size is: ' + set.size);
// has method returns a boolean, true if the item is in the set
console.log(set.has(1));
// add a number
set.add(6);
// delete a number
set.delete(1);
// iterate over each element using a callback
set.forEach((el) => {
console.log(el);
});
// remove all the entries from the set
set.clear();
除了缺少某些功能的IE之外,所有主流浏览器现在都完全支持集。有关确切的参考,请参阅mdn docs。
答案 6 :(得分:3)
使用裸javascript对象来模拟集合有两个问题:首先,一个对象可以有一个继承的属性,它会拧紧“in”运算符,其次,你只能以这种方式存储标量值,制作一组对象是不可能的。因此,集合的实际实现应提供方法add
和contains
,而不是普通in
和属性分配。
答案 7 :(得分:3)
你可以尝试Buckets,它是一个javascript数据结构库,拥有操作集所需的一切。
答案 8 :(得分:1)
let mySet = new Set()
mySet.add(2) // Set {2}
mySet.add(7) // Set {2, 7}
mySet.add(7) // Set {2, 7}
mySet.add('my text') // Set {2, 7, 'my text'}
let myObj = { a: 1, b: 2 }
mySet.add(myObj) // Set {2, 7, 'my text', {...}}
mySet.has(2) // true
mySet.has(myObj) // true
mySet.size // 4
迭代
for (let item of mySet) console.log(item) // 2, 7, 'my text', {a:1, b:2}
mySet.forEach(value => console.log(value)) // 2, 7, 'my text', {a:1, b:2}
转换为数组
var myArr = Array.from(mySet) // [2, 7, 'my text', {a:1, b:2}]
❕Set提供的最独特功能是Set对象中的每个值都必须是 独特。因此,您不能添加重复的值。