在 JavaScript 中创建 Set 的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8363564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:41:54  来源:igfitidea点击:

Ways to create a Set in JavaScript?

javascriptset

提问by helpermethod

In Eloquent JavaScript, Chapter 4, a set of values is created by creating an object and storing the values as property names, assigning arbitrary values (e.g. true) as property values. To check if the value is already contained in the set, the inoperator is used:

在 Eloquent JavaScript 第 4 章中,通过创建对象并将值存储为属性名称,将任意值(例如 true)分配为属性值来创建一组值。要检查该值是否已包含在集合中,请使用in运算符:

var set = {};

if (!'Tom' in set) { 
  set.Tom = true;
}

Is this idiomatic JavaScript? Wouldn't be using an array even better?

这是惯用的 JavaScript 吗?使用数组不是更好吗?

var set = [];

if (!'Tom' in set) { 
  set.push = 'Tom';
}

回答by John

Setsare now available in ES2015 (aka ES6, i.e. ECMAScript 6). ES6 has been the current standard for JavaScript since June 2015.

集合现在在 ES2015(又名 ES6,即 ECMAScript 6)中可用。自 2015 年 6 月以来,ES6 一直是 JavaScript 的当前标准。

ECMAScript 6 has the data structure Set which works for arbitrary values, is fast and handles NaN correctly. -Axel Rauschmayer, Exploring ES6

ECMAScript 6 具有适用于任意值的数据结构 Set,速度快且能正确处理 NaN。- Axel Rauschmayer探索 ES6

First two examples from Axel Rauschmayer'sbook Exploring ES6:

Axel Rauschmayer 的Exploring ES6 中的前两个例子:

Managing single elements:

管理单个元素:

> let set = new Set();
> set.add('red')

> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false

Determining the size of a Set and clearing it:

确定 Set 的大小并清除它:

> let set = new Set();
> set.add('red')
> set.add('green')

> set.size
2
> set.clear();
> set.size
0

I would check out Exploring ES6if you want to learn more about Sets in JavaScript. The book is free to read online, but if you would like to support the author Dr. Axel Rauschmayeryou can purchase the book for around $30.

如果你想了解更多关于 JavaScript 中的 Sets,我会查看Exploring ES6。这本书可以免费在线阅读,但如果您想支持作者Axel Rauschmayer 博士,您可以花 30 美元左右的价格购买这本书。

If you want to use Sets and ES6 now you can use Babel, the ES6 to ES5 transpiler, and its polyfills.

如果你现在想使用 Sets 和 ES6,你可以使用Babel,ES6 到 ES5 的转译器,以及它的 polyfill。

Edit: As of June 6th, 2017 most of the major browsers have full Set support in their latest versions (except IE 11). This means you may not need babel if you don't care to support older browsers. If you want to see compatibility in different browsers including your current browser check Kangax's ES6 compatibility table.

编辑:截至 2017 年 6 月 6 日,大多数主要浏览器在其最新版本(IE 11 除外)中都具有完整的 Set 支持。这意味着如果您不关心支持旧浏览器,您可能不需要 babel。如果您想查看包括当前浏览器在内的不同浏览器的兼容性,请查看Kangax 的 ES6 兼容性表

EDIT:

编辑:

Just clarification on initialization. Sets can take any synchronous iterable in their constructor. This means they can take not just arrays but also strings, and iterators. Take for example the following array and string initialization of a set:

只是澄清初始化。集合可以在其构造函数中采用任何同步迭代。这意味着它们不仅可以接受数组,还可以接受字符串和迭代器。以集合的以下数组和字符串初始化为例:

const set1 = new Set(['a','a','b','b','c','c']);
console.log(...set1);
console.log(set1.size);
const set2 = new Set("aabbcc");
console.log(...set2);
console.log(set2.size);

Both outputs of the array and string are the same. Note that ...set1is the spread syntax. It appears that each element of the iterable is added one by one to the set, so since both the array and string have the same elements and since the elements are in the same order the set is created the same. Another thing to note about sets is when iterating over them the iteration order follows the order that the elements were inserted into the set. Here's an example of iterating over a set:

数组和字符串的输出都是相同的。请注意,这...set1传播语法。似乎迭代的每个元素都被一个一个地添加到集合中,因此由于数组和字符串都具有相同的元素,并且由于元素的顺序相同,因此创建的集合也是相同的。关于集合要注意的另一件事是在迭代它们时,迭代顺序遵循元素插入到集合中的顺序。下面是一个迭代集合的例子:

const set1 = new Set(['a','a','b','b','c','c']);
for(const element of set1) {
  console.log(element);
}

Since you can use any iterable to initialize a set you could even use a iterator from a generator function. Here is two such examples of iterator initializations that produce the same output:

由于您可以使用任何可迭代对象来初始化集合,因此您甚至可以使用生成器函数中的迭代。这是产生相同输出的两个这样的迭代器初始化示例:

// a simple generator example
function* getLetters1 () {
  yield 'a';
  yield 'a';
  yield 'b';
  yield 'b';
  yield 'c';
  yield 'c';
}

// a somewhat more commonplace generator example
// with the same output as getLetters1.
function* getLetters2 (letters, repeatTimes) {
  for(const letter of letters) {
    for(let i = 0; i < repeatTimes; ++i) { 
      yield letter;
    }
  }
}

console.log("------ getLetters1 ------");
console.log(...getLetters1());
const set3 = new Set(getLetters1());
console.log(...set3);
console.log(set3.size);

console.log("------ getLetters2 ------");
console.log(...getLetters2('abc', 2));
const set4 = new Set(getLetters2('abc', 2));
console.log(...set4);
console.log(set4.size);

These examples' generator functions could just be written to not repeat, but if the generator function is more complicated and as long as the following doesn't impact performance too negatively you could use the Set method to help get only values from a generator that don't repeat.

这些示例的生成器函数可以写成不重复,但如果生成器函数更复杂,并且只要以下内容不会对性能产生太大的负面影响,您可以使用 Set 方法来帮助仅从不重复的生成器中获取值不重复。

If you want to know more about sets without reading Dr. Rauschmayer's chapter of his book you can check out the MDN docs on Set. MDN also has more examples of iterating over a set such as using forEachand using the .keys, .values, and .entriesmethods. MDN also has examples such as set union, set intersection, set difference, symmetric set difference, and set superset checking. Hopefully most of those operations will become available in JavaScript without needing to build your own functions supporting them. In fact, there is this TC39 proposal for new Set methodswhich should hopefully add the following methods to Set in JavaScript at some future point in time if the proposal reaches stage 4:

如果你想在不阅读 Rauschmayer 博士的书中的章节的情况下了解更多关于 Set 的信息,你可以查看Set 上MDN 文档。MDN还具有在一组迭代的更多的例子,例如使用forEach和使用.keys.values以及.entries方法。MDN 也有集合并集、集合交集、集合差、对称集合差、集合超集检查等例子。希望这些操作中的大多数都可以在 JavaScript 中使用,而无需构建自己的函数来支持它们。事实上,TC39 提出了关于新 Set 方法的提案,如果提案达到第 4 阶段,它有望在未来某个时间点将以下方法添加到 JavaScript 中的 Set 中:

  • Set.prototype.intersection(iterable) - method creates new Set instance by set intersection operation.
  • Set.prototype.union(iterable) - method creates new Set instance by set union operation.
  • Set.prototype.difference(iterable) - method creates new Set without elements present in iterable.
  • Set.prototype.symmetricDifference(iterable) - returns Set of elements found only in either this or in iterable.
  • Set.prototype.isSubsetOf(iterable)
  • Set.prototype.isDisjointFrom(iterable)
  • Set.prototype.isSupersetOf(iterable)
  • Set.prototype.intersection(iterable) - 方法通过设置交集操作创建新的 Set 实例。
  • Set.prototype.union(iterable) - 方法通过 set union 操作创建新的 Set 实例。
  • Set.prototype.difference(iterable) - 方法创建新的 Set,没有元素出现在 iterable 中。
  • Set.prototype.symmetricDifference(iterable) - 返回仅在 this 或 iterable 中找到的元素集。
  • Set.prototype.isSubsetOf(可迭代)
  • Set.prototype.isDisjointFrom(iterable)
  • Set.prototype.isSupersetOf(可迭代)

回答by Chris Dutrow

I use dict objects as sets. This works with strings and numbers, but I suppose would cause problems if you wanted to have a set of objects using custom equality and comparison operators:

我使用 dict 对象作为集合。这适用于字符串和数字,但我想如果您想要使用自定义相等和比较运算符的一组对象会导致问题:

Creating a set:

创建一个集合:

var example_set = 
{
    'a':true,
    'b':true,
    'c':true
}

Testing for inclusion in a set

测试是否包含在集合中

if( example_set['a'] ){
    alert('"a" is in set');
}

Adding an element to a set

向集合中添加元素

example_set['d'] = true;

Removing an element from a set

从集合中删除元素

delete example_set['a'];

delete example_set['a'];

回答by Jon Newmuis

Sets do not allow duplicate entries and don't typically guarantee predefined ordering. Arrays do both of these, thus violating what it means to be a set (unless you do additional checks).

集合不允许重复条目,并且通常不保证预定义的排序。数组同时执行这两项操作,因此违反了集合的含义(除非您进行额外检查)。

回答by Justin Niessner

The first way is idiomatic JavaScript.

第一种方式是惯用的 JavaScript。

Any time you want to store a key/value pair, you must use a JavaScript object. As for arrays, there are several problems:

任何时候要存储键/值对,都必须使用 JavaScript 对象。至于数组,有几个问题:

  1. The index is a numerical value.

  2. No easy way to check to see if a value is in an array without looping through.

  3. A set doesn't allow duplicates. An array does.

  1. 指数是一个数值。

  2. 没有简单的方法可以在不循环的情况下检查值是否在数组中。

  3. 集合不允许重复。数组可以。

回答by benjaminz

If you want to create a set from an array, simply do:

如果要从数组创建一个集合,只需执行以下操作:

let arr = [1, 1, 2, 1, 3];
let mySet = new Set(arr); // Set { 1, 2, 3 }

This is a sugar syntax that I quite fancied when programming in Python, so glad that ES6 finally made it possible to do the same thing.

这是我在用 Python 编程时非常喜欢的一种糖语法,很高兴 ES6 终于让做同样的事情成为可能。

NOTE: then I realize what I said didn't directly answer your question. The reason you have this "hack" in ES5 is because lookup time in an object by keys is significantly faster (O(1)) than in an array (O(n)). In performance critical applications, you can sacrifice this bit of readability or intuition for better performance.

注意:然后我意识到我所说的并没有直接回答你的问题。在 ES5 中进行这种“hack”的原因是,通过键在对象中的查找时间(O(1))比在数组中的查找时间(O(n))要快得多。在性能关键的应用程序中,您可以牺牲这种可读性或直觉以获得更好的性能。

But hey, welcome to 2017, where you can use proper Setin all major modern browsers now!

但是,嘿,欢迎来到 2017,在那里您现在可以在所有主要的现代浏览器中使用正确的Set

回答by Willem van der Veen

Sets in ES6/ES2015:

设置在ES6/ ES2015

ES6/ES2015now has built in sets. A set is data structure which allows storage of unique values of any type, whether this are primitive values or object references. A set can be declared using the ES6built in set constructor in the following manner:

ES6/ES2015现在内置了集合。集合是允许存储任何类型的唯一值的数据结构,无论是原始值还是对象引用。可以通过ES6以下方式使用内置的集合构造函数声明集合:

const set = new Set([1, 2, 3, 4, 5]);

When creating a set using the Set constructor our newly created set object inherits from the Set.prototype. This has all sorts of auxiliary methods and properties. This allows you to easily do the following things:

当使用 Set 构造函数创建一个集合时,我们新创建的集合对象继承自Set.prototype. 这具有各种辅助方法和属性。这使您可以轻松地执行以下操作:

Example:

例子:

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();

Browser compatibility:

浏览器兼容性:

All major browser now fully support sets except IE where some features are missing. For exact reference please refer to the mdn docs.

除了缺少某些功能的 IE 之外,所有主要浏览器现在都完全支持集。如需准确参考,请参阅mdn 文档

回答by georg

There are two problems with using bare javascript objects to emulate sets: first, an object can have an inherited property which would screw the "in" operator and second, you can only store scalar values in this way, making a set of objects is not possible. Therefore, a realistic implementation of Sets should provide methods addand containsinstead of plain inand property assignments.

使用裸 javascript 对象来模拟集合有两个问题:首先,一个对象可以有一个继承的属性,这会破坏“in”运算符,其次,您只能以这种方式存储标量值,使一组对象不是可能的。因此,Set 的实际实现应该提供方法addcontains不是简单的in和属性分配。

回答by Daniel

You can try Buckets, is a javascript data structure library and has everything you need to manipulate sets.

您可以尝试Buckets,它是一个 javascript 数据结构库,拥有操作集合所需的一切。

回答by Hasan Sefa Ozalp

Basic creation and usage of Set object

Set对象的基本创建和使用

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

Iteration

迭代

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}

Convert to array

转换为数组

var myArr = Array.from(mySet)             // [2, 7, 'my text', {a:1, b:2}]

? The most distinct feature Set offers is every value in Set object must be unique. So you can not add duplicate values.

? Set 提供的最独特的功能是 Set 对象中的每个值都必须是唯一的。所以你不能添加重复的值。