Swift Tutorial 4 – Collection Types Tutorial in Swift

Swift provides three main collection types we can use to store groups of related values. Arrays are linearly ordered by an index starting at zero. Sets contain unordered, unique values. Dictionaries store an unordered collection of key-value pairs.

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.

Table of contents

Arrays

Intro to Swift-4-1

The above image shows what an array looks like graphically. Essentially, arrays are ordered lists of elements of the same type where the ordering is delineated through a set of indices. Even if an array is empty, it can only hold values of a particular type. In addition to this restriction, it is very important to note that Swift arrays are zero-indexed so the first element is at index zero!

Let’s look at some ways we can declare an array.

var someInts = [Int]()
var zeros = [Int](repeating: 0, count: 75)
zeros.count
var arrayLiteral = [1, 2, 3, 4, 5, 6, 7]

The first line shows how to create an empty array. We can instantiate an array of any type; just substitute the type in place of Int in the square brackets. We can even pre-populate it with a repeated value as shown in the second line. zeros.count  should return 75 since we populated it with 75 zeros. All arrays have a property called count  that returns how many elements there are in that array. If we want to pre-populate our array with some values, we can declare a variable and put a comma-separated list of values in square brackets. Swift will use type inference to determine the type of array it should be.

A quick note on emptiness: we can determine whether or not an array is empty by using the isEmpty property on an array. If we wanted to empty an array, we can do so by setting the array equal to the empty array.

todoList = []
if todoList.isEmpty {
    print("Done for the day!")
}

Arrays declared using var are mutable types, meaning that we can modify them after they’ve been instantiated. There are two ways to append to an array: the append(…)  function or the compound addition operator (+=).

todoList.append("Buy groceries")
todoList += ["Finish homework"]
todoList += ["Complete exam review", "Complete book problems"]

Using the compound addition operator, we can append multiple elements to the end of the array. If we wanted to position an element at a specific index in the array, we can do that with the following function.

todoList.insert("Clean room", at:0)

This should also help stress the point that arrays are zero-index so the first element is at index zero. Now that we’ve discussed insertion into an array, let’s look at how we can retrieve and update data in an array using indices.

var firstTask = todoList[0]
todoList[1] = "Buy milk"

var firstFourTasks = todoList[0...3]
todoList[0...1] = ["Buy bread", "Buy eggs"]

We can access and update an element of an array using that element’s index. We can even access and update a subset of the array using the triple dot notation shown above. The triple dot notation will include the last index in the subset so the line above retrieves four elements (at indices 0, 1, 2, and 3).

Instead of updating an element, we can remove it entirely by using the following method. The return value is the element that was removed, but we don’t have to use the return value if we don’t need to. In addition to removing an element at a particular index, we can quickly remove the last element as well.

let doneWithFirstTask = todoList.remove(at: 0)
let doneWithAnotherTask = todoList.removeLast()

It’s important to note that removing an item in the middle of the array will close up any of the gaps. If we deleted an item from index 2, whatever was in index 3 will now be in index 2.

We can iterate over an array in two ways: only by element or by element and index. We’ll discuss the for-in loop later in control flow, but the below loops will iterate through the array.

for task in todoList {
    print(task)
}

for (index, task) in todoList.enumerated() {
    print("Task #\(index+1) is \(task)")
}

The second for-in loop uses something akin to value binding since the enumerated()  function returns a tuple. Also note we’re adding 1 to the index so that the first task is #1 and not #0.

Sets

Intro to Swift-4-2

A set is an unordered collection of distinct values. Set is unordered since elements don’t have any ID associated with them like arrays do. Sets also cannot contain any duplicates. Initializing sets is similar to how we initialize arrays so we must specify the type of the variable. Let’s see how to declare a set.

var tools: Set<String> = ["Screwdriver", "Pliers", "Saw"]
var tools: Set = ["Screwdriver", "Pliers", "Saw"]

The above two lines of code are exactly the same. The second line uses Swift’s type inference to deduce that the set is a set of strings. Sets have similar properties to arrays such as getting the number of elements in the set using the count  property of the set and checking for the empty set using isEmpty. We can add items to a set using the insert(…)  function. We don’t have to specify an index since sets are unordered.

tools.insert("Hammer")

As for removing items in a set, the remove(…)  function will return an optional variable of the same type as everything in the set. If the element we’re trying to remove is in the set is actually in the set, we get back that item. If it isn’t then we get back nil. We can also clear a set of it’s elements using the removeAll()  function.

if let removedTool = tools.remove("Soldering iron") {
    print("Found my soldering iron")
} else {
    print("Cannot find my soldering iron!")
}

tools.removeAll()

We can iterate over a set exactly like we can an array, except sets don’t have the enumerated()  function since they’re unordered. Look at the example of the first for-in loop in the arrays section above. We can also iterate over a sorted list of the set elements by calling sorted()  similar to enumerated()  for arrays.

The most useful thing about sets is the set operations we can perform with them. Below is an image of all of the set operators we can perform with their Swift code above the Venn diagrams.

basic-set-operations

Set intersection will return any elements shared between A and B. Set union will return any elements that are in either A or B. A subtract B will remove any elements in B from A and return those elements.

Another thing that’s useful about sets is membership. Below is an image of three sets and various operations and their values.

set-operations

 

A and B are equal sets, then they should have the same elements. If B is a subset of A, then every element in B is also in A. If A is a superset of B, then B is a subset of A. If B is a strict subset of A, then every element in B is also in A and B and A are not equal! If two sets are disjoint, they don’t share any elements.

Dictionaries

Intro to Swift-4-3

A dictionary stores key-value pairs. All of the keys have to the be same type and all of the values have to be the same type, but the keys do not have to be the same type as the values. In addition, each unique key has to be associated with a value. In other words, we can’t have two of the same keys! We also can’t have a key map to two different values! Dictionaries are similar to sets in that the pairs aren’t in any specific order so we’ll see how some of the operations will be the same. Let’s see how we can formally and informally create dictionaries.

var houseNumbers = [Int: String]()
houseNumbers[1225] = "Smiths"
houseNumbers = [:]

The first line creates an empty dictionary with keys of Ints and values of Strings. The second line creates a key-value pair mapping: 1225 maps to “Smiths”. The final line clears the dictionary. We can create a dictionary in-place as well.

var houseNumbers: [Int: String] = [1225: "Smiths", 1227: "Johnsons"]
var houseNumbers = [1225: "Smiths", 1227: "Johnsons"]

The above two lines do the exact same thing. The second line, like sets and arrays, uses Swift’s type inference to deduce the types of the keys and values. As in arrays and sets, dictionaries also have the count  and isEmpty  properties we can use. Suppose we have the following dictionary:

var stockTickers = ["GOOG": "Google", "AAPL": "Apple", "MSFT": "Microsoft"]

We can access the keys using array subscript notation, but using the key instead of the index. We can retrieve, update, or create elements all using this subscript notation.

var company = stockTickers["AAPL"]
stockTickers["GOOG"] = "Google Inc."
stockTickers["FB"] = "Facebook"

As an alternative to updating values through the subscript syntax, we can use a function to do this for us. The benefit of using this function is that we can retrieve the old value. We use optional binding similar to how we remove elements from the set.

if let oldCompany = stockTickers.updateValue("Google Inc.", forKey:"GOOG") {
    print("Old value: \(oldCompany)")
}

We can use the subscript syntax in optional binding if we’re going to be looking for a key-value pair that we’re not entirely sure is in the dictionary. Then the if statement will execute if the pair is in the dictionary: if let possibleComp = stockTickers[“YAHOO”] { … } . To delete key-value pairs from the dictionary, we can either set the value to nil or we can do the same thing we did in the code sample above, except use removeValueForKey(…) .

stockTickers["FB"] = nil

if let removedStock = stockTickers.removeValue(forKey: "FB") {
    print("Removed \(removedStock)")
} else {
    print ("Unable to find value!")
}

Since dictionaries store two different sets of values, there are three ways we can iterate over a dictionary: key-value pairs, just keys, and just values.

for (ticker, company) in stockTickers {
    print("\(ticker)->\(company)")
}

for ticker in stockTickers.keys {
    print("Stock ticker: \(ticker)")
}

for company in stockTickers.values {
    print("Company: \(company)")
}

The first loop iterates through all of the key-value pairs; the second loop iterates through just the keys; and the last loop iterates through all of the values. As a last comment about dictionaries, we can get an array of the keys and values by converting the dictionaries representation of the keys and values into arrays as follows.

let tickers = [String](stockTickers.keys)
let companies = [String](stockTickers.values)

To recap, we discussed Swift’s three major collection types: arrays, sets, and dictionaries. An array is list of values, all of the same type, ordered by an index that starts at zero. A set is an unordered collection of unique values, all of the same type. They’re most useful when you need to perform set operations such as union, intersection, subtraction, and various membership tests. Finally, a dictionary is a map of key-values pairs such that all of the keys are of the same type, the values are of the same type, and the keys are unique. The keys are values don’t have to be the same type. They’re useful when we need to create a map between two different entities. We also saw how to add, retrieve, update, and delete values from all three collection types as well.