How to Make Friends with Sets in JavaScript

Brian Greig
BetaPage
Published in
4 min readSep 27, 2019

One of the additions to ES6 is the Set object. Details on the Set Object can be read on the MDN Web Docs on Sets. You probably remember sets from discrete math when you had to draw Venn Diagrams on the blackboard. This is the same concept. The idea is you create a collection of unique primitives (strings, numbers) from a broader set of data. This will allow you to see only the unique values and strip away any redundancy. The interesting
thing about sets is how you can use them to compare against other sets.

The example we are going to use is a very rudimentary social network. We’ll start with an array of people. Every person has a name and an array representing all of their friends. Just for simplicity sake we are going to assume that someones first name is enough to uniquely identify them:

let people = [
{ name: "Brian",
friends: ["Rob", "Eileen", "Isabel"] },
{ name: "Isabel",
friends: ["April", "Andrea", "Eileen", "Brian"] },
{ name: "Rob",
friends: ["Eileen", "Mike", "Brian"] },
{ name: "Eileen",
friends: ["Rob", "Mike", "Brian"] }
];

With our data in hand we are going to want to create a few sets. The first is going to be our friends. In this the 0th element in the array is me, Brian. We are going to use the ES6 Set constructor to create a set called myFriends. We’ll iterate through the array and assign each name to the set using the add() method:

const me = people[0].name;
const myFriends = new Set();
people[0].friends.forEach(f => {
myFriends.add(f);
});
console.log(myFriends)
// Set(3) [ "Rob", "Eileen", "Isabel" ]

The result is a set of three elements for each element in the Array. Like any good social network we want to then take this list and look up all of their friends to see if maybe there is someone we are unacquainted with. We will iterate through each array of friends in the array of people. We can then take each of those people and add them into one superset.

Here we will start to see the value the Set object. Since sets are collections of unique objects it will disregard any duplicate values. What we will end up with is reduced the number of elements across all four arrays (thirteen gets reduced to seven). Since this new set includes all of my friends we call it a superset. The list of my friends is a subset of the group of all possible friends

const possibleFriends = new Set();
people.forEach(p => {
p.friends.forEach(f => {
possibleFriends.add(f);
});
});
console.log(possibleFriends)
// Set(7)
// [ "Rob", "Eileen", "Isabel", "April", "Andrea", "Brian", "Mike" ]

As expected we ended up with a total of seven people in our superset. This is good but it is not what you want for a social network.

What we want is a list of possible friends that aren’t already in my list of friends. We also don’t want to recommend myself as a friend (although I do enjoy my own company). What we actually want is the difference between the two. In order to find this delta we are going to create a new set called unacquainted that is a copy of possibleFriends.

We will then iterate through this set deleting everyone I already know. We’ll also delete me from the list. What we will be left with are three unique individuals who are friends once removed that I am not already friends with.

const unacquainted = new Set(possibleFriends);
unacquainted.delete(me);
for (var elem of myFriends) {
unacquainted.delete(elem);
}
//Set(3) [ "April", "Andrea", "Mike" ]
console.log(unacquainted);

Hopefully this gives you a better understanding of how sets work in JavaScript. Review the MDN Web Docs for more information on some of the other methods associated with sets such as `has` which checks is a particular element is part of a collection or `entries` which returns all values in an array. You also might want to brush up on some of the different set operations. The three most common are:

  • Union is in either set or both sets
  • Intersection only in both sets
  • Difference in one set but not the other

CAUTION Since objects are references you can’t use them in your set comparisons. In the example below checking if the object with the matching store number is in the set will come back false whereas the set with the primitive values will come back true:

let set1 = new Set()
.add({"storeNumber": 1234})
.add({"storeNumber":4567})
console.log(set1.has({"storeNumber": 1234}))
//false
let set2 = new Set()
.add(1234)
.add(4567)
console.log(set2.has(1234))
//true

Sets are a powerful tool for comparing primitives in your applications. At the time of this writing this feature is fairly well supported including support for IE11. Hopefully you will start seeing usages in your applications for where sets can provide a better way of representing data.

--

--

Brian Greig
BetaPage

Web designer, developer, business intelligence specialist, and all around nerdy tech guy.