(Ad, please don’t block.)

`Set`

)- 35.1 Using Sets
- 35.1.1 Creating Sets
- 35.1.2 Adding, removing, checking membership
- 35.1.3 Determining the size of a Set and clearing it
- 35.1.4 Iterating over Sets

- 35.2 Examples of using Sets
- 35.3 What Set elements are considered equal?
- 35.4 Missing Set operations
- 35.4.1 Union (
`a`

∪`b`

) - 35.4.2 Intersection (
`a`

∩`b`

) - 35.4.3 Difference (
`a`

\`b`

) - 35.4.4 Mapping over Sets
- 35.4.5 Filtering Sets

- 35.4.1 Union (
- 35.5 Quick reference:
`Set<T>`

- 35.5.1 Constructor
- 35.5.2
`Set<T>.prototype`

: single Set elements - 35.5.3
`Set<T>.prototype`

: all Set elements - 35.5.4
`Set<T>.prototype`

: iterating and looping - 35.5.5 Symmetry with
`Map`

- 35.6 FAQ: Sets

Before ES6, JavaScript didn’t have a data structure for sets. Instead, two workarounds were used:

- The keys of an object were used as a set of strings.
- Arrays were used as sets of arbitrary values. The downside is that checking
*membership*(if an Array contains a value) is slower.

Since ES6, JavaScript has the data structure `Set`

, which can contain arbitrary values and performs membership checks quickly.

There are three common ways of creating Sets.

First, you can use the constructor without any parameters to create an empty Set:

```
const emptySet = new Set();
.equal(emptySet.size, 0); assert
```

Second, you can pass an iterable (e.g., an Array) to the constructor. The iterated values become elements of the new Set:

`const set = new Set(['red', 'green', 'blue']);`

Third, the `.add()`

method adds elements to a Set and is chainable:

```
const set = new Set()
.add('red')
.add('green')
.add('blue');
```

`.add()`

adds an element to a Set.

```
const set = new Set();
.add('red'); set
```

`.has()`

checks if an element is a member of a Set.

`.equal(set.has('red'), true); assert`

`.delete()`

removes an element from a Set.

```
.equal(set.delete('red'), true); // there was a deletion
assert.equal(set.has('red'), false); assert
```

`.size`

contains the number of elements in a Set.

```
const set = new Set()
.add('foo')
.add('bar');
.equal(set.size, 2) assert
```

`.clear()`

removes all elements of a Set.

```
.clear();
set.equal(set.size, 0) assert
```

Sets are iterable and the `for-of`

loop works as you’d expect:

```
const set = new Set(['red', 'green', 'blue']);
for (const x of set) {
console.log(x);
}// Output:
// 'red'
// 'green'
// 'blue'
```

As you can see, Sets preserve *insertion order*. That is, elements are always iterated over in the order in which they were added.

Given that Sets are iterable, you can use `Array.from()`

to convert them to Arrays:

```
const set = new Set(['red', 'green', 'blue']);
const arr = Array.from(set); // ['red', 'green', 'blue']
```

Converting an Array to a Set and back, removes duplicates from the Array:

```
.deepEqual(
assertArray.from(new Set([1, 2, 1, 2, 3, 3, 3])),
1, 2, 3]); [
```

Strings are iterable and can therefore be used as parameters for `new Set()`

:

```
.deepEqual(
assertnew Set('abc'),
new Set(['a', 'b', 'c']));
```

As with Map keys, Set elements are compared similarly to `===`

, with the exception of `NaN`

being equal to itself.

```
> const set = new Set([NaN, NaN, NaN]);
> set.size1
> set.has(NaN)true
```

As with `===`

, two different objects are never considered equal (and there is no way to change that at the moment):

```
> const set = new Set();
> set.add({});
> set.size1
> set.add({});
> set.size2
```

Sets are missing several common operations. Such an operation can usually be implemented by:

- Converting the input Sets to Arrays by spreading into Array literals.
- Performing the operation on Arrays.
- Converting the result to a Set and returning it.

`a`

∪ `b`

)Computing the union of two Sets `a`

and `b`

means creating a Set that contains the elements of both `a`

and `b`

.

```
const a = new Set([1,2,3]);
const b = new Set([4,3,2]);
// Use spreading to concatenate two iterables
const union = new Set([...a, ...b]);
.deepEqual(Array.from(union), [1, 2, 3, 4]); assert
```

`a`

∩ `b`

)Computing the intersection of two Sets `a`

and `b`

means creating a Set that contains those elements of `a`

that are also in `b`

.

```
const a = new Set([1,2,3]);
const b = new Set([4,3,2]);
const intersection = new Set(
Array.from(a).filter(x => b.has(x))
;
)
.deepEqual(
assertArray.from(intersection), [2, 3]
; )
```

`a`

\ `b`

)Computing the difference between two Sets `a`

and `b`

means creating a Set that contains those elements of `a`

that are not in `b`

. This operation is also sometimes called *minus* (−).

```
const a = new Set([1,2,3]);
const b = new Set([4,3,2]);
const difference = new Set(
Array.from(a).filter(x => !b.has(x))
;
)
.deepEqual(
assertArray.from(difference), [1]
; )
```

Sets don’t have a method `.map()`

. But we can borrow the one that Arrays have:

```
const set = new Set([1, 2, 3]);
const mappedSet = new Set(
Array.from(set).map(x => x * 2)
;
)
// Convert mappedSet to an Array to check what’s inside it
.deepEqual(
assertArray.from(mappedSet), [2, 4, 6]
; )
```

We can’t directly `.filter()`

Sets, so we need to use the corresponding Array method:

```
const set = new Set([1, 2, 3, 4, 5]);
const filteredSet = new Set(
Array.from(set).filter(x => (x % 2) === 0)
;
)
.deepEqual(
assertArray.from(filteredSet), [2, 4]
; )
```

`Set<T>`

`new Set<T>(values?: Iterable<T>)`

^{[ES6]}If you don’t provide the parameter

`values`

, then an empty Set is created. If you do, then the iterated values are added as elements to the Set. For example:`const set = new Set(['red', 'green', 'blue']);`

`Set<T>.prototype`

: single Set elements`.add(value: T): this`

^{[ES6]}Adds

`value`

to this Set. This method returns`this`

, which means that it can be chained.`const set = new Set(['red']); .add('green').add('blue'); set.deepEqual( assertArray.from(set), ['red', 'green', 'blue'] ; )`

`.delete(value: T): boolean`

^{[ES6]}Removes

`value`

from this Set. Returns`true`

if something was deleted and`false`

, otherwise.`const set = new Set(['red', 'green', 'blue']); .equal(set.delete('red'), true); // there was a deletion assert.deepEqual( assertArray.from(set), ['green', 'blue'] ; )`

`.has(value: T): boolean`

^{[ES6]}Checks whether

`value`

is in this Set.`const set = new Set(['red', 'green']); .equal(set.has('red'), true); assert.equal(set.has('blue'), false); assert`

`Set<T>.prototype`

: all Set elements`get .size: number`

^{[ES6]}Returns how many elements there are in this Set.

`const set = new Set(['red', 'green', 'blue']); .equal(set.size, 3); assert`

`.clear(): void`

^{[ES6]}Removes all elements from this Set.

`const set = new Set(['red', 'green', 'blue']); .equal(set.size, 3); assert.clear(); set.equal(set.size, 0); assert`

`Set<T>.prototype`

: iterating and looping`.values(): Iterable<T>`

^{[ES6]}Returns an iterable over all elements of this Set.

`const set = new Set(['red', 'green']); for (const x of set.values()) { console.log(x); }// Output: // 'red' // 'green'`

`[Symbol.iterator](): Iterable<T>`

^{[ES6]}Default way of iterating over Sets. Same as

`.values()`

.`const set = new Set(['red', 'green']); for (const x of set) { console.log(x); }// Output: // 'red' // 'green'`

`.forEach(callback: (value: T, key: T, theSet: Set<T>) => void, thisArg?: any): void`

^{[ES6]}Feeds each element of this Set to

`callback()`

.`value`

and`key`

both contain the current element. This redundancy was introduced so that this`callback`

has the same type signature as the`callback`

of`Map.prototype.forEach()`

.You can specify the

`this`

of`callback`

via`thisArg`

. If you omit it,`this`

is`undefined`

.`const set = new Set(['red', 'green']); .forEach(x => console.log(x)); set// Output: // 'red' // 'green'`

`Map`

The following two methods mainly exist so that Sets and Maps have similar interfaces. Each Set element is handled as if it were a Map entry whose key and value are both the element.

`Set.prototype.entries(): Iterable<[T,T]>`

^{[ES6]}`Set.prototype.keys(): Iterable<T>`

^{[ES6]}

`.entries()`

enables you to convert a Set to a Map:

```
const set = new Set(['a', 'b', 'c']);
const map = new Map(set.entries());
.deepEqual(
assertArray.from(map.entries()),
'a','a'], ['b','b'], ['c','c']]
[[; )
```

`.size`

, while Arrays have a `.length`

?The answer to this question is given in §33.6.4 “Why do Maps have a `.size`

, while Arrays have a `.length`

?”.

**Quiz**

See quiz app.