Getting Started With the Swift Collections Package

Learn about three new data structures available in the Swift Collections package: Deque, OrderedSet and OrderedDictionary. By Felipe Laso-Marsetti.

Leave a rating/review
Download materials
Save for later
Share

If you’ve written code in languages other than Swift, you might have wondered why Swift doesn’t have ordered sets or dictionaries. Wonder no more! With the new open-source Swift Collections package by Apple, you now have the data structures for Swift you’ve been seeking.

In this tutorial, you’ll learn about:

  • The three new data structures in the package: Deque, OrderedSet and OrderedDictionary.
  • The differences and advantages of these new structures versus the built-in collection types in the Swift Standard Library.
  • An alternative to ordered dictionaries that already exists in the Swift Standard Library.
Note: This tutorial assumes you’re familiar with the Set, Array and Dictionary collection types. If you’re not, check out our Swift Fundamentals Course first!

OK. It’s time to get started!

Getting Started

Download the project materials by clicking the Download Materials button at the top or bottom of the tutorial. Open the starter project, which contains an Xcode workspace with a playground in it. The playground already includes the Swift Collections package as a dependency. You’ll need to wait for Xcode to download and build the package before you can start.

Note: This tutorial used Arena to create a Swift playground that incorporates a Swift package as a dependency.

The playground contains three pages: one for Deque, one for OrderedSet and one for OrderedDictionary.

Each page already contains code to demonstrate how to use the closely-matching data structures that Swift already contains: Array, Set and Dictionary, as well as KeyValuePairs, which you may not have heard of before.

Run the code in each of the playground pages to check out the results. Each page creates one of the built-in data structures, then performs commonly-used operations on each. This will help set up a baseline of what the built-in types can do compared to the data structures available in the Swift Collections package.

Now that you’re familiar with the starter project, you’ll learn about the new data structures available in the Swift Collections package, starting with Deque.

Swift with some numbers

Understanding Deque

Deque — pronounced “Deck”, derived from Double-Ended Queue — holds a sequence of values, just like an array. Unlike an array, a deque is super efficient at inserting or removing elements from its beginning or its end. An array is only optimized for adding or removing elements at its end.

You can think of the difference between the two queues by visualizing Array as a vertical stack of cubes and Deque as a horizontal row of cubes. It’s easy to add an element at the bottom of a stack of vertical cubes as long as there aren’t too many cubes. But as you add more cubes, adding a cube at the bottom of the stack becomes more difficult. It has a performance of O(n).

Adding cubes at the beginning or end of your row of cubes (Deque) is quick and easy. The performance of adding a cube at either end is O(1).

Note: O(n) and O(1) are ways of describing how the performance of a function is affected by the size of the data it is working on. O(n) means that as the data grows larger, the performance gets slower. O(1) means that the performance is always the same, regardless of the size of the data.

Deque vs. Array

Now that you know what a deque is, you can jump straight into coding with it.

Working With Deque

Creating a deque is similar to creating an array. To try it, open the Deque page of MyPlayground and scroll to the bottom. Add the following code:

var deque = Deque<String>()

This creates a Deque ready to hold String elements. You can also create deque literals as you would with an array with the following code:

var anotherDeque: Deque = ["An Element"]

This creates a Deque with a single element.

Appending and Prepending With Deque

As you learned above, Deque efficiently inserts items both at the beginning and the end.

Deque offers the following ways to add items to a sequence:

  • append(_:): Adds an item to the end of the sequence, exactly like Array.
  • append(contentsOf:): Adds the contents of a collection to the end of the sequence, again exactly like Array.
  • prepend(_:): Adds an item to the beginning of the sequence.
  • prepend(contentsOf:): Adds the contents of a collection to the beginning of the sequence.

To add items to the start of an array, you’d have to use insert(_:at:) to specify not only the element you’re adding but also the index where you’re inserting it.

Add the following code at the end of your playground page to add some elements to your deque:

deque.append("Element 2")
deque.prepend("Element 1")
deque.append("Element 3")

Because Deque respects the order in which you added the elements, your playground will print out the following:

["Element 1", "Element 2", "Element 3"]

Your sequence’s contents are printed in the expected order given the order of your append and prepend calls.

Add the following code to your playground to test out adding the contents of a collection to your deque:

deque.append(contentsOf: ["Element 4", "Element 5"])
deque.prepend(contentsOf: ["Element 0"])

Run the playground and you’ll see the deque now contains elements 0 to 5, in order.

Removing Items From a Deque

Like Array, Deque also supports removing items from the beginning or end of a sequence. Add the following code to see this in action:

deque.removeFirst()
deque

removeFirst() acts like it would in an Array, removing the element at the beginning of the sequence. Your deque must not be empty when calling this.

You can use popLast() to remove items at the end of the sequence. It works the same as removeLast(), but it returns an optional value and is fine to use on a deque that may be empty. Add the following code to the playground to see how it works:

deque.popLast()
deque

Originally, your queue contained these elements:

["Element 1", "Element 2", "Element 3", "Element 4", "Element 5"]

Now, it looks like this:

["Element 1", "Element 2", "Element 3", "Element 4"]

The same concept applies to its counterpart, popFirst(), which removes elements at the beginning of the sequence.

Add the code below to the playground:

deque.popFirst()
deque

Before this call, your dequeue looked like:

["Element 1", "Element 2", "Element 3", "Element 4"]

Now, it looks like this:

["Element 2", "Element 3", "Element 4"]

You might be thinking that slightly more convenient methods when dealing with items at the start of a collection are not worth including a whole dependency in your project for. The real benefit of using deques over arrays comes down to performance, which you’ll look at next.