Learn how to leverage JavaScript’s Set with practical examples. This comprehensive guide covers union, difference, symmetricDifference, intersection and more.
Sets are collections in JavaScript that store unique values. Unlike Arrays, Sets automatically handle duplicates and provide powerful operations for working with unique data. While Arrays are great for ordered collections where duplicates are allowed, Sets excel at managing unique items and performing mathematical set operations.
The Set data structure was introduced in ES6, but recent additions have brought more methods that make Sets even more useful for modern development. Let’s explore these new operations and see how they can solve common programming challenges.
The union()
method combines two Sets into a new Set containing all unique elements from both Sets. Think of it as merging two collections while automatically removing duplicates.
Let’s look at an example where we have various roles for different categories of users, call them basic
and admin
. We can get all the roles in the system while avoiding duplicates using the union
method as follows:
// Define sets of roles for different systems
const basicRoles = new Set(['user', 'viewer', 'commenter']);
const adminRoles = new Set(['admin', 'moderator', 'user']);
// Combine all roles using union
const allRoles = basicRoles.union(adminRoles);
console.log(allRoles);
// Output: Set (5) {"user", "viewer", "commenter", "admin", "moderator"}
// Notice how 'user' appears only once, even though it was in both sets
This method is useful when you need to combine permissions, features or any collection where duplicates are not needed.
The difference()
method creates a new Set containing elements that exist in the first set but not in the second. It’s like asking, “What do I have that you don’t?”
This method comes in handy when doing analytical work. Imagine a scenario where you have two users who bought similar items but you want to find out what’s unique to one of them. Here’s how you’d do that with the difference()
method.
// Items in two different shopping carts
const cart1 = new Set(['book', 'laptop', 'headphones', 'mouse']);
const cart2 = new Set(['book', 'laptop', 'keyboard']);
// Find items unique to cart1
const uniqueToCart1 = cart1.difference(cart2);
console.log(uniqueToCart1);
// Output: Set (2) {"headphones", "mouse"}
Notice that keyboard
, which is unique to cart2
, is not included because we’re only looking at what’s unique to cart1
. This method is valuable when you need to find items that exist exclusively in one collection but not in another.
The symmetricDifference()
method returns elements that are in either Set, but not in both. It’s useful for finding elements that are unique to each Set.
Our next example is about feature flags. Feature flags are a software development concept that allows you to enable or disable a feature without modifying the source code or requiring a redeploy. Given two distinct environments, production and development, let’s see how we can find which features are different in those environments:
// Feature flags in different environments
const prodFeatures = new Set(['dark-mode', 'search', 'notifications']);
const devFeatures = new Set(['dark-mode', 'search', 'debug-panel']);
// Find features that differ between environments
const diffFeatures = prodFeatures.symmetricDifference(devFeatures);
console.log([...diffFeatures]);
// Output: Set (2) {"notifications", "debug-panel"}
The symmetricDifference()
method helps compare two versions or states to find differences, no matter which side they are on.
The intersection()
method creates a new Set containing only the elements present in both Sets. It’s perfect for finding common elements between two sets.
Let’s look at an example where we want to find hobbies that are common between two users:
// User interests
const user1Interests = new Set(['coding', 'music', 'hiking', 'photography']);
const user2Interests = new Set(['gaming', 'music', 'photography', 'cooking']);
// Find common interests
const commonInterests = user1Interests.intersection(user2Interests);
console.log(commonInterests);
// Output: Set (2) {"music", "photography"}
Only music
and photography
are present in both Sets, so they form the intersection. Unique interests such as coding
, hiking
, gaming
and cooking
are excluded. In essence, use the intersection()
method to identify commonalities between two collections, which can be particularly useful for recommendation systems or matching algorithms.
The isDisjointFrom()
method checks if two Sets have no elements in common. It returns true if the Sets are completely different.
Imagine if you’re building the next Calendly or a calendar app where you want to check if the meeting about to be scheduled conflicts with an existing meeting. You can do that with isDisjointedFrom()
. Here’s how:
// Time slots (simplified as hour numbers)
const meeting1Times = new Set([9, 10, 11]);
const meeting2Times = new Set([14, 15, 16]);
// Check if meetings conflict
const noConflict = meeting1Times.isDisjointFrom(meeting2Times);
console.log(noConflict); // Output: true
This Set operation is ideal for checking if two collections are distinct, which is useful in scheduling, resource allocation or conflict detection scenarios.
The isSubsetOf()
method checks if all elements of the first Set exist in the second.
Let’s look at an example to verify that a job candidate meets minimum requirements.
// Required and candidate skills
const requiredSkills = new Set(['typescript', 'react']);
const candidateSkills = new Set(['typescript', 'react', 'node', 'python']);
// Check if candidate has all required skills
const hasRequiredSkills = requiredSkills.isSubsetOf(candidateSkills);
console.log(hasRequiredSkills); // Output: true
Given a collection of required skills and a candidate’s skills, we can determine if the candidate meets the criteria using the isSubsetOf()
method.
This isSupersetOf()
method verifies if the first Set contains all elements of the second.
// Required and implemented features
const requiredFeatures = new Set(['login', 'signup']);
const implementedFeatures = new Set(['login', 'signup', 'logout', 'profile']);
// Check if all required features are implemented
const allFeaturesImplemented = implementedFeatures.isSupersetOf(requiredFeatures);
console.log(allFeaturesImplemented); // Output: true
This example checks if we implemented all the required features. This is much simpler than writing loops and conditional statements to achieve the same result.
Before ES6, JavaScript didn’t have a data structure for sets. JavaScript now has a Set
data structure which can contain arbitrary values and performs membership checks quickly. We explored the new Set
operations added after ES6. Here’s what we learned:
union
, difference
and intersection
for combining/filtering datasets.symmetricDifference
for finding unique entries.isSubsetOf
/isSupersetOf
for containment checks.isDisjointFrom
for exclusivity verification.Method | Description | Returns |
---|---|---|
union() | All unique elements from both sets | New Set |
difference() | Elements only in the first set | New Set |
symmetricDifference() | Elements in either but not both | New Set |
intersection() | Elements common to both | New Set |
isDisjointFrom() | No shared elements | Boolean |
isSubsetOf() | All elements contained in other set | Boolean |
isSupersetOf() | Contain all elements of another set | Boolean |
These operations make Sets an invaluable tool for managing unique collections, comparing data and solving common programming challenges. By mastering these operations, you’ll write more expressive code when working with collections, from user permissions to inventory management. Remember that all mutation-free methods return new Sets, making them safe for functional programming patterns.
The examples provided show practical applications, but there are many more possibilities. As you work with Sets, you’ll discover they can simplify many common programming tasks and make your code more expressive.
Peter is a software consultant, technical trainer and OSS contributor/maintainer with excellent interpersonal and motivational abilities to develop collaborative relationships among high-functioning teams. He focuses on cloud-native architectures, serverless, continuous deployment/delivery, and developer experience. You can follow him on Twitter.