How to Get the Difference Between Two Set Objects in JavaScript
A common task when working with Set objects is to find the "difference" between them. This can mean one of two things:
- Asymmetric Difference: The elements that are in
setAbut not insetB. - Symmetric Difference: The elements that are in either
setAorsetB, but not in both.
This guide will teach you the modern and efficient methods for calculating both types of differences, leveraging the high performance of Set.has() lookups.
Goal 1: Getting the Asymmetric Difference (A - B)
The asymmetric difference answers the question: "What elements does Set A have that Set B does not?"
For example, we need to find the elements that exist in setA but are missing from setB.
// Problem: Find elements in setA that are not in setB.
const setA = new Set(['a', 'b', 'c', 'd']);
const setB = new Set(['a', 'b']);
// Expected result: a new Set containing {'c', 'd'}
Recommended Solution: filter() with has()
The most concise way to solve this is to convert one Set to an array, filter it, and then convert the result back into a Set.
function getDifference(setA, setB) {
const difference = new Set(
[...setA].filter(element => !setB.has(element))
);
return difference;
}
// Example Usage:
const setA = new Set(['a', 'b', 'c', 'd']);
const setB = new Set(['a', 'b']);
const difference = getDifference(setA, setB);
console.log(difference); // Output: Set(2) { 'c', 'd' }
How it works:
[...setA]: The spread syntax convertssetAinto a temporary array (e.g.,['a', 'b', 'c', 'd'])..filter(element => ...): This method iterates over the new array.!setB.has(element): For eachelement, we check if it exists insetB. Thehas()method is extremely fast (O(1) on average). The!negates the result, so the filter keeps only the elements that are not insetB.new Set(...): The final array of filtered elements is passed to theSetconstructor to create the resultingSet.
An Alternative: The for...of Loop
A for...of loop is slightly more verbose but can be more performant on very large sets, as it avoids creating an intermediate array.
function getDifferenceForOf(setA, setB) {
const difference = new Set();
for (const element of setA) {
if (!setB.has(element)) {
difference.add(element);
}
}
return difference;
}
Goal 2: Getting the Symmetric Difference
The symmetric difference answers the question: "What elements are unique to each Set?"
For example, we need to find all elements that appear in setA or setB, but not in both.
// Problem: Find elements that are in one set but not the other.
const setA = new Set(['a', 'b', 'c', 'd']);
const setB = new Set(['a', 'b', 'e', 'f']);
// Expected result: a new Set containing {'c', 'd', 'e', 'f'}
Recommended Solution
We can solve this by performing the asymmetric difference in both directions and then combining the results.
function getSymmetricDifference(setA, setB) {
const diffA = [...setA].filter(element => !setB.has(element));
const diffB = [...setB].filter(element => !setA.has(element));
return new Set([...diffA, ...diffB]);
}
// Example Usage:
const setA = new Set(['a', 'b', 'c', 'd']);
const setB = new Set(['a', 'b', 'e', 'f']);
const symmetricDifference = getSymmetricDifference(setA, setB);
console.log(symmetricDifference); // Output: Set(4) { 'c', 'd', 'e', 'f' }
An Alternative: The for...of Loop
A clever for...of loop can also compute the symmetric difference efficiently.
function getSymmetricDifferenceForOf(setA, setB) {
const difference = new Set(setA); // Start with a clone of setA
for (const element of setB) {
if (difference.has(element)) {
// If the element is already in our set, it's in both, so remove it.
difference.delete(element);
} else {
// If it's not in our set, it's unique to setB, so add it.
difference.add(element);
}
}
return difference;
}
Conclusion
Finding the difference between two Set objects is a common operation that showcases the power and performance of the Set data structure.
- The key to all of these operations is the fast
set.has()method for lookups. - For the asymmetric difference (elements in A but not B), the most concise method is to
filteroneSetagainst the other. - For the symmetric difference (elements in either, but not both), you can either perform the asymmetric difference twice or use a single, clever
for...ofloop.