Skip to main content

ES6 — Set vs Array — What and when?

6 min read

Older Article

This article was published 7 years ago. Some information may be outdated or no longer applicable.

Let’s find out.

What is Set and what is Array?

Array is a structure representing a block of data (numbers, objects, etc.) allocated in consecutive memory.

Example: [1,2,3,2]

How about Set?

Set, more familiar as a maths concept, is an abstract data type which contains only distinct elements/objects without needing to be ordered by index.

Example: {1,2,3}

By definition, Array and Set are technically different concepts.

The biggest difference you’ll spot: elements in Array can be duplicate (unless you prevent it), and in Set, they can’t (no matter what you do).

Array is considered an “indexed collection” type of data structure, while Set is considered a “keyed collection”.

A quick reminder:

Indexed collections are collections of data ordered by an index value

Keyed collections are collections which use keys; they contain elements which are iterable in the order of insertion.

So if they’re different, why compare them?

In practice, given the same data set (no duplicates), you could use either Array or Set to store it. But depending on the use case, picking the right structure helps you deliver the optimal solution. To make that choice, we need to understand how they’re built and what they can do. We’ve covered “who they are”, so let’s move on to “how to build one” in JS.

Constructing

Array

Array is very direct. To declare a new array in JS, you can use the literal syntax:

var arr = []; //Empty array
var arr = [1, 2, 3]; //Array which contains 1,2,3

Or use the built-in constructor:

var arr = new Array(); //empty array
var arr = new Array(1, 2, 3); //Array which contains 1,2,3

Or even cooler:

var arr = new Array(); //empty array
var arr = new Array(1, 2, 3); //Array which contains 1,2,3

Side notes:

One piece of advice: don’t use new Array() unless you really really really need to, because:

  • It performs much slower than the normal [] literal. (A topic for another article, maybe.)
  • [] saves more typing time (try it)
  • You can end up making classic mistakes such as:
var arr1 = new Array(10); //arr1[0] = undefined but arr1.length = 10
var arr2 = [10]; // arr2[0] = 10 and arr2.length = 1;
var arr3 = new Array(1, 2, 3); //[1,2,3]
var arr4 = [1, 2, 3]; //[1,2,3]

So rule number one: keep it simple.

Set

Set has a built-in constructor. There’s no shortcut like with Array.

Set([iterable])

To create a new set, use the new syntax:

var emptySet = new Set();
var exampleSet = new Set([1, 2, 3]);

But definitely not: new Set(1);

Set receives an iterable object as its input parameter and creates the set from it. You can construct a set from an array, but it’ll only include distinct elements from that array. No duplicates.

And you can convert a set back to an array using Array.from():

var set = new Set([1, 2, 3]); // {1,2,3}
var arr = Array.from(set); //[1,2,3]

Right, now that we know how to create them, what about their capabilities?

Let’s do a small comparison between the most basic methods Array/Set provides:

Locating an element / Accessing an element

  • Set doesn’t support random access to an element by index like Array does:
console.log(set[0]); //undefined
console.log(arr[0]); //1
  • Because Array data is stored in consecutive memory, the CPU can fetch it much faster due to pre-fetching.
  • So in general, accessing elements in Array (one after another, as in a for loop) is quicker and more efficient compared to other abstract data types.
  • Checking if an element exists in Set has simpler syntax than Array: Set.prototype.has(value) vs Array.prototype.indexOf(value)
console.log(set.has(0)); // boolean - false
console.log(arr.indexOf(0)); // -1
console.log(set.has(1)); //true
console.log(arr.indexOf(1)); //0

With Array, you need an extra check if you want a boolean:

var isExist = arr.indexOf(1) !== -1;

Note: ES6 does provide Array.prototype.includes() which behaves similarly to has(), but it isn’t supported widely (not in IE, surprise).

Add/Insert new element

  • Adding a new element to Array can be done in O(1) using Array.prototype.push(), which appends to the end.
arr.push(4); //[1,2,3,4]
  • Or in O(n) using Array.prototype.unshift(), which prepends to the beginning (where n is the length of the current array).
arr.unshift(3); //[3,1,2,3]
arr.unshift(5, 6); //[5,6,3,1,2,3]
  • In Set, there’s only one way to add a new element: Set.prototype.add(). Because Set must maintain the “distinct” property, each call to add() needs to check all members for duplicates. In general add() takes O(n) running time. But thanks to hash table implementation, add() in Set will likely take only O(1).
set.add(3); //{1,2,3}
set.add(4); //{1,2,3,4}

So Set performs roughly the same as Array when adding elements. What about removing?

Remove element

  • Array gives you several methods to remove an element: Pop() removes and returns the last element. This takes O(1).
arr.pop(); //return 4, [5,6,1,2,3]

Shift() removes and returns the first element. This takes O(n).

arr.shift(); //return 5; [6,1,2,3]

Splice(index, deleteCount) removes deleteCount elements starting from index. This can take up to O(n).

arr.splice(0, 1); //[1,2,3]
  • In Set, we use:

Delete(element) removes a specific given element from Set.

set.delete(4); //{1,2,3}

Clear() removes all elements from Set.

set.clear(); //{}
  • While Array doesn’t have a native method to remove a specific element by value (unless you know its index), Set has delete(). Simple and clean.

Array does provide many more native methods (reduce(), reverse(), sort(), etc.) compared to Set, which currently only has the basics mentioned above. So why would you ever prefer Set?

So, when is Set better? And when is Array better?

  • Set isn’t meant to replace Array entirely. It provides additional support for what Array is missing.
  • Since Set only contains distinct elements, it makes life much easier when you know in advance you want to avoid duplicates.
  • Basic set operations like union(), intersect(), difference() are easily implemented using the native built-in methods. The delete() method makes intersect/union between 2 Sets much more comfortable than doing the same with 2 Arrays.
  • Array is the right choice when you need elements ordered for quick access, when you’re doing heavy modification (removing and adding elements), or when you need direct index access (try doing Binary Search on a Set instead of an Array: how would you access the middle element?).

Conclusion

In general, Set doesn’t have a huge clear advantage over Array, except in specific cases: when you want to maintain distinct data with minimal effort, or when you’re working with multiple distinct data sets using basic set operations and don’t need direct element access.

Otherwise, Array should always be the choice. The CPU has an easier time fetching the element when it’s needed.

Do you agree? Feel free to discuss.

Disclaimer: This post is originally posted in FrontEnd Weekly

If you’d like to catch up with me sometimes, follow me on Twitter | Facebook or simply visit my portfolio website.