Learn JavaScript in Construct, part 9: Data structures

19

Index

Features on these Courses

Stats

5,666 visits, 11,817 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY-NC 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Published on 19 Nov, 2021. Last updated 16 Dec, 2021

Set

In JavaScript, a Set is a collection of unique values. That means if you try to add the same value twice, it will only be added once to the collection. This is a useful feature if you intend to have unique values, but another reason to use it is it's more efficient than arrays for this purpose.

For example imagine you want everyone who uses your program to have a unique username, and that 1 million people have already signed up. When the next person comes along and tells you what username they want, you have to check it's not one of the 1 million usernames already in use. With an array, this would mean having to check every single username in the list - making 1 million checks. However Set uses special search algorithms to be able to make this check much more efficiently.

On the other hand this search improvement means the ability to access elements by their index is lost. So we can check if items are in the set, but not directly access, say, the 5th element. If all you need to do though is check if a username is already used, that's not a problem. This is a typical example of the many trade-offs involved in programming, and why it's important to choose the right data structure for the job.

Sets don't have special syntax in JavaScript like there is for arrays - they look and work more like objects. The basic usage is shown below.

// Create a new empty set
let mySet = new Set();

// Add a string to the set
mySet.add("😀");

// Display the set in the console
console.log("mySet is: ", mySet);

Note how a new empty set is created with new Set(), and a value is added with the add() method.

A set can be created with some initial values by passing an array. Despite the use of an array here, the set will read all these values and add them in to its own data structure - the array is just a way to provide the initial values.

// Create a set with two strings
let mySet = new Set(["😀", "👽"]);

// Add another string to the set
mySet.add("👾");

// Display the set in the console
// It now has: 😀, 👽, 👾
console.log("mySet is: ", mySet);

So far this works a lot like an array, but we can start to see the difference if we try to add the same string twice:

// Create a set with two strings
let mySet = new Set(["😀", "👽"]);

// Add another string to the set
mySet.add("👾");

// Add the same string again - this does nothing
// as it's already in the set
mySet.add("👾");

// Display the set in the console
// It still has: 😀, 👽, 👾
console.log("mySet is: ", mySet);

Adding a value already in the set does nothing, as the set only stores unique values.

Sets have a size property that indicates the number of items in the set. This is similar to the length property on arrays, but remember that sets only store unique values, so adding a value won't increase the size if it's already in the set.

let mySet = new Set(["😀", "👽"]);
console.log(`The set size is ${mySet.size}`);

// This value is already in the set, so nothing is added
mySet.add("👽");

// The set size is still the same
console.log(`The set size is still ${mySet.size}`);

The delete() method can be used to remove an item.

let mySet = new Set(["😀", "👽", "👾"]);

mySet.delete("👽");

// Set has 😀 and 👾
console.log("mySet is: ", mySet);

A value that is not in the set can still be deleted - it just does nothing. There's also a clear() method that deletes all items.

The has() method returns a boolean indicating whether a given value is in the set.

let mySet = new Set(["😀", "👽"]);
console.log("mySet is: ", mySet);

// true
console.log("mySet has 😀: ", mySet.has("😀"));

// false
console.log("mySet has 👾: ", mySet.has("👾"));

Iterating a set

Since sets can't access elements by their index, the only way to iterate the values is with the "for-of" style loop, as in the example below.

let mySet = new Set(["😀", "👽", "👾"]);

for (let item of mySet)
{
	console.log(`mySet has item ${item}`);
}

JavaScript does define the order for sets, so it's not quite correct to say they are unordered. The loop will iterate items in insertion order, i.e. the order they were added to the set. However items cannot be re-ordered, including the fact that if you add an item already in a set, the order of the existing item isn't changed. In general this means the order of a set is not particularly useful - the main reason JavaScript defines an order is to make sure programs work consistently across different platforms. So it's best to think about sets as a collection where the ordering is not important. Our previous example of storing a list of 1 million usernames to check which are in use is a good example of something where the order doesn't matter - you just want to know if a given username is in the list or not, and you don't need to know where it comes in the list exactly.

Converting to/from array

We already covered how to convert an array to a set: if you pass an array when creating a set, it adds all the elements of the array to the set.

let mySet = new Set(["😀", "👽"]);

Notice that as with using add(), if the array has duplicates, it will only add unique values. Passing an array is essentially a shortcut to call add() on each element.

let mySet = new Set(["😀", "👽", "👽"]);

// Set has just 2 elements: 😀 and 👽
console.log(`mySet size is ${mySet.size}`);

A set can also be converted back to an array using the spread operator ... in the form [...mySet]:

let mySet = new Set(["😀", "👽"]);
let asArray = [...mySet];
console.log("asArray: ", asArray);

You can think of the [ and ] as creating a new array, and ...mySet meaning the content of the array is every item in mySet.

This also provides a good way to remove duplicate elements from an array. Converting an array to a set removes duplicates, and then converting a set back to an array gives you the unique items as an array again. The code sample below shows a function that does this.

function removeDuplicates(arr)
{
	// Convert array to set to remove duplicates
	let asSet = new Set(arr);
	
	// Return set converted back to an array
	return [...asSet];
}

console.log("Example 1: ", removeDuplicates(["😀", "👽", "👾", "😀"]));

console.log("Example 2: ", removeDuplicates(["👽", "👽", "👽", "👾", "🦄", "👾"]));
  • 3 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • Love these tutorials, many thanks!

  • What made you guys to change your mind, in such odd manner? Before there has been multiple statements that scirra is not there to teach users JS and especially base JS.

    While I can see this opens up huge market and new opportunities with schools and other people. And could level up scirra with army of gamemaking toolsets: editor, runtime, events, JS, animating with meshes, art and more

    If something similar is on verge to be made, i hope C3 does not suffer and left aside.

  • Greate job Ashley, keep going!