Dictionary in Swift

Where? How does the Swift compiler store values in a Dictionary?

Image for post
Image for post
Photo by Dmitry Ratushny on Unsplash

These are called HashMaps in Java, but whatever language you are coming from a dictionary is a data structure that maps keys to values.

Prerequisites:

  • Be able to produce a “Hello, World!” iOS application (guide HERE)
  • Knowledge of optionals (guide HERE)
  • Be familiar with += to increment values (guide HERE)
  • Knowing something about force unwrapping would be useful (guide HERE)
  • Knowing about Mutability is important (guide HERE)

Terminology

Character: A written character, usually associated with a letter of the alphabet

Dictionary: The association between keys and values (where all the keys are of the same type, and all values are of the same type)

Increment: An operator (+=) that adds one to the operand

Integer: A number that has no fractional part, that is no digits after the decimal point

Key-value pairs: A set of two linked data items, a unique identifier (key) and an item of data (value)

Optional: Swift introduced optionals that handle the absence of a value, simply by declaring if there is a value or not. An optional is a type on it’s own!

String: A collection of Characters

What is a dictionary

A dictionary allows you to store unordered groups of values searchable by key. Each value needs to have the same type, but each key needs to have the same type.

One important part to think about is the fast access that a dictionary gives to the values it stores.

A dictionary with Integer keys and Values

Initializing

Initializing a Dictionary in Swift isn’t too tricky, but there are a couple of ways of doing it.

We can define the type of the Dictionary and initilize it without keys or values:

var myDictionary: [Int: Int] = [:]

or we can use Swift’s type inference and create an empty dictionary of Integer keys and values.

var myDictionary = [Int: Int]()

Adding values to a dictionary

In myDictionary shown above, we can add values to the dictionary. In this example, the dictionary stores Integers as values and keys so we are expecting to see a good number of Integers here.

An example of the use of this might be the test scores for students in a school (if you’ve numbered the students, which surely no teacher would do?). If we number a student as 4, we can record their test score of 17.

myDictionary[4] = 17

This maps the key to the value in myDictionary

Image for post
Image for post

We can repeat the trick. Our student numbered 8 has a score of 7. In Swift we add it through:

myDictionary[8] = 7
Image for post
Image for post

printing the values gives us the following output to the console:

[8: 7, 4: 11]

Changing values in a dictionary

This works much like adding values in a dictionary.

Taking our example of student scores, what if student 4 actually had a score of 11 and therefore the dictionary is wrong?

No problem, we can just adjust the value just like we are adding it for the first time:

myDictionary[4] = 11
Image for post
Image for post

The alternative: updateValue
It is possible to use a function provided by Swift, that updates a value if it already exists. If the key exists the updated value is returned, if not nil is returned.

myDictionary.updateValue(1, forKey: 0) // return nil

Isn’t that nice?

Retrieving values in a dictionary

When we retrieve values from the dictionary an optional is returned.

let studentFour: Int? = myDictionary[4] // 11

If you try to retreive a value that is absent from the dictionary, nil will be returned.

let studentFive: Int? = myDictionary[5] // nil

Increment values in a dictionary: default values

To increment the values in the dictionary, (so if all the values in the dictionary needed to be increased by one in our example we made a mistake and increase each student by one) we can use the increment += operator.

myDictionary[4]! += 1 // 12
myDictionary[8]! += 1 // 8

Now the more eagle-eyed reader will notice there is something not great going on here — force unwapping. This means that if a value does not exist then the application will crash at runtime, which is obviously not ideal.

So, to be clear, the following will crash with a rather upsetting error.

myDictionary[5]! += 1 // error
Image for post
Image for post

which makes perfect sense, as adding one to nil logically would result in an error.

If we assume that a key that isn’t yet in the dictionary should have a value of zero, we can use a default value:

myDictionary[5, default: 0] += 1

which gives us the following picture (as a diagram)

Image for post
Image for post

And note: we didn’t crash (Excellent).

Iterate through values in a dictionary

When we iterate through the values in the Dictionary we can treat them much like any other collection type (that is Set or Array in Swift), but we can certainly move through each element and print out the key and value.

for pupil in myDictionary {
print (pupil.key, pupil.value)
}

Sorting a dictionary

This is also the same for all Swift’s collection types. Here we can see a common sort where the values are arranged in descending order of values

myDictionary.sorted{
return $0.value > $1.value
}

Filtering a dictionary

This is the same as general filtering in Swift.

Here is a quick example to return all of the dictionary entries that have an even key

myDictionary.filter{return $0.key % 2 == 0}

That is, the following are returned: [8: 8, 4: 12]

General dictionaries

We can see from the Integer keys and Integer value examples that the type of a Dictionary is represented by square brackets with the key proceeding the value.

Here is an example of mixing Integer and Strings as a combination of keys and values.

Image for post
Image for post

Creating combinations of Int and String Dictionaries

we can use Swift’s type inference to easily create these key value pairs. Note all of these examples are mutable (stored with a var) rather than immutable with a let.

var intstring = [1: "a"] // [Int: String]
var stringint = ["a": 1] // [String: Int]
var intint = [1: 1] // [Int: Int]
var stringstring = ["a": "a"] // [String: String]

Copy on write

Copy on write behaviour extends to any dictionary since they are a value type.

In practice this means that we can just make a copy of our dictionary and, well the values are copied.

var mySecondDictionary = myDictionary

which then means printing out both the original and copy

print (myDictionary, mySecondDictionary)

produces the same result to the console

// [4: 12, 8: 8, 5: 1] [4: 12, 8: 8, 5: 1]

Now of course the same rules apply as to all value types — so changes to the copy do not reflect in the original instance.

Why use dictionaries

They are often used for high-performance computing applications like caches and databases as the lookup for dictionaries is constant.

Conclusion

A dictionary in Swift is a wonderful thing. Quick to access and easy to use, this is a collection type that you should certainly investigate while learning Swift. If you’re read this article, you’ve already done so (so well done you!).

Extend your knowledge

  • Apple have a dictionary with documentation (HERE)
  • Copy on write has a guide (HERE)

The Twitter contact:

Any questions? You can get in touch with me HERE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store