What are Sets?
Sets are a type of object in JavaScript that let you store unique values of any type, whether primitive values or object references. You can think of them as a collection of items that have no duplicates. For example, you can have a set of numbers, like {1, 2, 3}, or a set of strings, like {“apple”, “banana”, “cherry”}. You can also have a set of arrays or objects as long as they are not equal to each other.
Set is a modern data structure in JavaScript. It was added to JavaScript in ES2015 (also known as ES6 or ECMAScript 6), which was the sixth edition of the ECMAScript standard and was finalized in June 2015.
Sets vs. Arrays: The Key Differences
While Sets and Arrays might seem similar at first glance, they have some key differences that make them suitable for different use cases. Here are some of the most notable differences between JavaScript Sets and Arrays:
- Uniqueness: Sets automatically ensure that each element is unique, whereas Arrays can contain duplicate values.
- Order: Arrays maintain the order of their elements, while Sets are unordered collections.
- Indexing: Arrays use numeric indices to access their elements, whereas Sets do not have indices.
- Performance: Sets generally perform better than Arrays for insertion, deletion, and lookup operations.
- Methods: Sets and Arrays have different methods available to manipulate and interact with their elements.
The purposes of Sets
The purpose of Sets JavaScript is to provide a data structure that can store and manipulate unique values of any type, whether primitive values or object references. Sets can be useful for performing operations such as checking membership, removing duplicates, finding intersections or unions, and iterating over values in insertion order. Sets can also be used to model abstract data types such as graphs, trees, stacks, queues, and more. Sets are compatible with Maps, which are another data structure that can store key-value pairs.
Some real-world use cases of Sets in modern web development are:
- To store a collection of unique items without worrying about duplicates or orders. For example, you can use a Set to store the names of your favorite fruits or the IDs of your online friends.
- To perform set operations such as union, intersection, difference, and symmetric difference. For example, you can use Sets to find the common elements or the exclusive elements between two arrays or other iterables.
- To implement algorithms that require fast lookups or hashing. For example, you can use Sets to check if a value is present in a collection or to implement a cache system.
- To create custom objects that have setters and getters for their properties. For example, you can use Sets to define a class that has a pseudo-property that executes a function whenever it is assigned a value.
Creating a Set
Creating a Set in JavaScript is as simple as using the Set constructor. You can either create an empty Set or initialize it with an iterable object, such as an Array or another Set. Here’s how you can create Sets in JavaScript:
// Creating an empty Set
const emptySet = new Set();
// Creating a Set with an Array
const arrayWithValues = [1, 2, 3, 4, 5];
const setFromArray = new Set(arrayWithValues);
// Creating a Set with a String
const stringToSet = 'hello';
const setFromString = new Set(stringToSet);
// Creating a Set with another Set
const originalSet = new Set([1, 2, 3]);
const newSet = new Set(originalSet);
Basic Set Operations
Count Elements in a Set
To count the number of elements in a Set, you can use the size property of the Set object:
const mySet = new Set(['Sling', 'Academy', 'JavaScript'])
const count = mySet.size
console.log(count) // 3
The size property returns the number of values in the Set, regardless of their type or order. Note that the size property is not a method, so you don’t need to use parentheses to access it.
Check if a Set contains a specific element
To check if a Set contains a specific element, you can use the has() method of the Set object. The has() method takes a value as an argument and returns true if the Set contains that value, or false otherwise.
Example:
// Create a Set
const fruits = new Set(["apple", "banana", "cherry"]);
// Check if the Set contains "apple"
const result = fruits.has("apple"); // result = true
// Check if the Set contains "orange"
const result2 = fruits.has("orange"); // result2 = false
The has() method uses the SameValueZero algorithm to compare values, which means that NaN is considered equal to NaN, and -0 is considered equal to +0. The has() method also works for any type of value, including objects and functions.
Example:
// Create a Set
const mySet = new Set([1, NaN, {x: 1}, () => {}]);
// Check if the Set contains NaN
const result = mySet.has(NaN); // result = true
// Check if the Set contains {x: 1}
const result2 = mySet.has({x: 1}); // result2 = false (different object references)
// Check if the Set contains () => {}
const result3 = mySet.has(() => {}); // result3 = false (different function references)
Adding new elements to a Set
The add(value) method inserts a new element with the specified value into the Set if there isn’t an element with the same value already in the Set. It returns the Set object itself, so you can chain multiple calls to add().
Example:
// Create a Set
const fruits = new Set();
// Add "apple" to the Set
fruits.add("apple");
// fruits = {"apple"}
// Add "banana" and "cherry" to the Set
fruits.add("banana").add("cherry");
// fruits = {"apple", "banana", "cherry"}
// Try to add "apple" again
fruits.add("apple");
// fruits = {"apple", "banana", "cherry"} (no change)
Remove elements from a Set
The delete(value) method removes the element associated with the specified value from the Set if it exists. It returns true if an element was successfully removed, or false otherwise.
Example:
// Create a Set
const fruits = new Set(['apple', 'banana', 'cherry']);
// Remove "banana" from the Set
const result = fruits.delete('banana');
// result = true, fruits = {"apple", "cherry"}
// Try to remove "orange" from the Set
const result2 = fruits.delete('orange');
// result2 = false, fruits = {"apple", "cherry"}
In case you want to remove all elements from a Set and leave it empty, use the clear() method. This method does not return any value.
Example:
// Create a Set
const fruits = new Set(["apple", "banana", "cherry"]);
// Clear the Set
fruits.clear();
// fruits = {}
Modifying an element in a Set
There is no direct way to modify an existing element in a Set since Sets do not have indexes or keys to access their elements. However, you can achieve the same effect by deleting the old element and adding the new one.
Example:
// Create a Set
const fruits = new Set(["apple", "banana", "cherry"]);
// Modify "banana" to "orange"
fruits.delete("banana");
fruits.add("orange");
// fruits = {"apple", "cherry", "orange"}
Different Ways to Iterate Through a Set
There are different ways to iterate through a Set in JavaScript, depending on your preference and use case.
Using a for…of loop
This is a simple and concise way to loop through the values of a Set in insertion order. You can use the break or continue statements to control the loop.
Example:
// Create a Set
const fruits = new Set(['apple', 'banana', 'cherry']);
// Loop through the Set using a for...of loop
for (const fruit of fruits) {
console.log(fruit);
}
Output:
apple
banana
cherry
Using the forEach() method
This is a functional way to loop through the values of a Set in insertion order. You need to provide a callback function that takes the value as an argument and performs some action on it. You can also access the Set object itself and an optional thisArg inside the callback.
Example:
// Create a Set
const fruits = new Set(['apple', 'banana', 'cherry']);
// Loop through the Set using a forEach() method
fruits.forEach(fruit => {
console.log(`I want to eat a ${fruit}`);
});
Output:
I want to eat a apple
I want to eat a banana
I want to eat a cherry
Using the values(), keys(), or entries() method
You can use the values() method to get an iterator object that contains the values of a Set in insertion order. You can then use the next() method or a for…of loop to access the values one by one.
Example:
// Create a Set
const fruits = new Set(['apple', 'banana', 'cherry']);
// Get an iterator object using a values() method
const iterator = fruits.values();
// Loop through the iterator using the next() method
console.log(iterator.next()); // logs {value: "apple", done: false}
console.log(iterator.next()); // logs {value: "banana", done: false}
console.log(iterator.next()); // logs {value: "cherry", done: false}
console.log(iterator.next()); // logs {value: undefined, done: true}
// Loop through the iterator using a for...of loop
for (const fruit of iterator) {
console.log(fruit);
// logs nothing (the iterator is exhausted)
}
Note that you can also use the keys() or entries() methods instead of the values() method, but they will return the same iterator object for a Set.
Advanced Set Operations
The union of 2 Sets
The union of two sets A and B is the set that contains all the elements that are in either A or B or both. In modern JavaScript (ES6 and beyond), you can use the spread operator (…) to create a new Set that is the union of two existing Sets.
Example:
// Create two Sets
const A = new Set([1, 2, 3]);
const B = new Set([3, 4, 5]);
// Create a new Set that is the union of A and B
const C = new Set([...A, ...B]);
console.log(C);
// C = {1, 2, 3, 4, 5}
The intersection of 2 Sets
The intersection of two sets A and B is the set that contains all the elements that are in both A and B. You can use the filter() method to create a new Set that is the intersection of two existing Sets.
Example:
// Create two Sets
const A = new Set([1, 2, 3]);
const B = new Set([3, 4, 5]);
// Create a new Set that is the intersection of A and B
const C = new Set([...A].filter((x) => B.has(x)));
console.log(C);
// {3}
Find the difference between 2 Sets
The difference between two sets A and B is the set that contains all the elements that are in A but not in B. The solution here is to use the filer() method.
Example:
// Create two Sets
const A = new Set([1, 2, 3]);
const B = new Set([3, 4, 5]);
// Create a new Set that is the difference of A and B
const C = new Set([...A].filter(x => !B.has(x)));
// C = {1, 2}
Find the symmetric difference between 2 Sets
The symmetric difference of two sets A and B is the set that contains all the elements that are in either A or B but not in both. The example below demonstrates the way to get the symmetric difference of two existing Sets:
// Create two Sets
const A = new Set([1, 2, 3]);
const B = new Set([3, 4, 5]);
// Create a new Set that is the symmetric difference of A and B
const C = new Set(
[...A].filter((x) => !B.has(x)).concat([...B].filter((x) => !A.has(x)))
);
// C = {1, 2, 4, 5}
Comparing 2 Sets
There are different ways to compare two Sets in JavaScript, depending on what you want to check.
Check if 2 Sets are equal
Two Sets are equal if they have the same size and the same values. At the time of writing, in JavaScript, there is no built-in method to check if two Sets are equal, but you can use a for…of loop, and the has() method to compare them.
Example:
// Create two Sets
const A = new Set([1, 2, 3]);
const B = new Set([3, 2, 1]);
// Check if A and B are equal
const areSetsEqual = (set1, set2) => {
// If the sizes are different, they are not equal
if (set1.size !== set2.size) {
return false;
}
// Loop through the values of set1
for (const value of set1) {
// If set2 does not have the same value, they are not equal
if (!set2.has(value)) {
return false;
}
}
// If all values match, they are equal
return true;
};
console.log(areSetsEqual(A, B));
// Output: true
Check whether one Set is a subset of another
A Set A is a subset of another Set B if every value in A is also in B. There is no built-in method to solve this task. However, we can easily define a custom function on our owns.
Example:
// Create two Sets
const A = new Set([1, 2]);
const B = new Set([1, 2, 3]);
// define a custom function to check if a set is a subset of another set
const isSubset = (set1, set2) => {
// Loop through the values of set1
for (const value of set1) {
// If set2 does not have the same value, set1 is not a subset
if (!set2.has(value)) {
return false;
}
}
// If all values match, set1 is a subset
return true;
};
console.log(isSubset(A, B));
// logs true
Check if one Set is a superset of another
A Set A is a superset of another Set B if every value in B is also in A. The example below demonstrates how to check whether Set A is the superset of Set B:
// Create two Sets
const A = new Set([1, 2, 3]);
const B = new Set([1, 2]);
// Check if A is a superset of B
const isSuperset = (set1, set2) => {
// Loop through the values of set2
for (const value of set2) {
// If set1 does not have the same value, set1 is not a superset
if (!set1.has(value)) {
return false;
}
}
// If all values match, set1 is a superset
return true;
};
console.log(isSuperset(A, B));
// Output: true
Set conversions
Convert a Set into an Array and vice versa
You can convert a Set to an array by using the spread operator (…) or the Array.from() method. You can convert an array to a Set by using the new Set() constructor.
Example:
// Create a Set
const fruits = new Set(['apple', 'banana', 'cherry']);
// Convert the Set to an array using the spread operator
const fruitsArray = [...fruits];
// fruitsArray = ["apple", "banana", "cherry"]
// Convert the Set to an array using the Array.from() method
const fruitsArray2 = Array.from(fruits);
// fruitsArray2 = ["apple", "banana", "cherry"]
// Convert an array to a Set using the new Set() constructor
const colorsArray = ['red', 'green', 'blue'];
const colorsSet = new Set(colorsArray);
// colorsSet = {"red", "green", "blue"}
Convert a Set into a String and vice versa
You can turn a Set into a string by using the join() method on an array converted from the Set. You can convert a string to a Set by using the new Set() constructor and passing the string as an argument.
Example:
// Create a Set
const letters = new Set('hello');
// Convert the Set to a string using the join() method
const lettersString = [...letters].join('');
// lettersString = "helo"
// Convert a string to a Set using the new Set() constructor
const nameString = 'John';
const nameSet = new Set(nameString);
// nameSet = {"J", "o", "h", "n"}
Conclusion
This long and comprehensive article covers everything you need to know about Sets in modern JavaScript. If you have any questions, feel free to leave a comment. We’re more than happy to hear your thoughts.
Happy coding & have a nice day!