在 JavaScript 中创建 Set 的方法?

发布于 2024-12-19 02:24:37 字数 324 浏览 2 评论 0原文

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

var set = {};

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

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

var set = [];

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

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 in operator is used:

var set = {};

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

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

var set = [];

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

戴着白色围巾的女孩 2024-12-26 02:24:37

Sets 现已在 ES2015(又名 ES6)中提供,即 ECMAScript 6)。自 2015 年 6 月以来,ES6 一直是 JavaScript 的当前标准。

ECMAScript 6 具有适用于任意数据结构 Set
值,速度快并且可以正确处理 NaN。 -阿克塞尔·劳施迈尔探索 ES6

Axel Rauschmayer 的 书中的前两个示例 探索 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 中 Set 的更多信息,我会查看 探索 ES6 。这本书可以免费在线阅读,但如果您想支持作者Dr. Axel Rauschmayer 您可以花大约 30 美元购买这本书。

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

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

编辑:

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

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

数组和字符串的输出是相同的。请注意 ...set1扩展语法。看起来可迭代的每个元素都被一一添加到集合中,因此由于数组和字符串都具有相同的元素,并且由于元素的顺序相同,所以创建的集合是相同的。关于集合需要注意的另一件事是,当迭代它们时,迭代顺序遵循元素插入集合中的顺序。这是迭代集合的示例:

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

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

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

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

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

  • Set.prototype.intersection(iterable) - 方法通过集合交集操作创建新的 Set 实例。
  • Set.prototype.union(iterable) - 方法通过集合联合操作创建新的 Set 实例。
  • Set.prototype.difference(iterable) - 方法创建新的 Set,但 iterable 中不存在元素。
  • Set.prototype.symmetryDifference(iterable) - 返回仅在 this 或 iterable 中找到的元素集合。
  • Set.prototype.isSubsetOf(可迭代)
  • Set.prototype.isDisjointFrom(可迭代)
  • Set.prototype.isSupersetOf(可迭代)

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

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

First two examples from Axel Rauschmayer's book 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:

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

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

I would check out Exploring ES6 if 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 Rauschmayer you can purchase the book for around $30.

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

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.

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 ...set1 is 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:

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.

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 forEach and using the .keys, .values, and .entries methods. 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 methods which should hopefully add the following methods to Set in JavaScript at some future point in time if the proposal reaches stage 4:

  • 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)
舟遥客 2024-12-26 02:24:37

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

创建集合:

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

测试是否包含在集合中< /strong>

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

向集合中添加元素

example_set['d'] = true;

从集合中删除元素

delete example_set['a'];

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:

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'];

无力看清 2024-12-26 02:24:37

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

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).

沉默的熊 2024-12-26 02:24:37

第一种方法是惯用的 JavaScript。

每当您想要存储键/值对时,都必须使用 JavaScript 对象。对于数组来说,有几个问题:

  1. 索引是一个数值。

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

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

The first way is idiomatic JavaScript.

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

  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.

夏日浅笑〃 2024-12-26 02:24:37

如果你想从数组创建一个集合,只需这样做:

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

这是我在使用 Python 编程时非常喜欢的糖语法,很高兴 ES6 终于可以做同样的事情了。

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

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

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.

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.

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

铃予 2024-12-26 02:24:37

ES6/ES2015 中的集合:

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

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

使用 Set 构造函数创建集合时,我们新创建的 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 文档

Sets in ES6/ES2015:

ES6/ES2015 now 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 ES6 built in set constructor in the following manner:

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:

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.

情仇皆在手 2024-12-26 02:24:37

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

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 add and contains instead of plain in and property assignments.

夜访吸血鬼 2024-12-26 02:24:37

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

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

心头的小情儿 2024-12-26 02:24:37

Set 对象

Basic creation and usage of Set object ????

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文